/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "stdafx.h"
#include "材质节点.h"
#include "节点编辑.h"
#include "节点/节点树.h"
#include "节点/插座/几何插座.h"
#include "节点/socket_utils.h"

#include "../插座/材质纹理插座.h"
#include "../插座/C_数值插座.h"
#include "../插座/list/list物体插座.h"
#include "../插座/list/list数值插座.h"

#include "../../node后端.h"

#include "异步解算/物理异步解算.h"
#include "材质纹理JIT函数绑定.h"

#include <随机数.h>
#include <JIT.h>
#include <core/shader_PBR.h>
#include <场景/intern/S_Scene.h>


static std::string g材质_参数 = "g材质_参数";




//static std::string f_着色器输出节点编译回调(C_节点基类* self, std::string& 声明, std::vector<std::string>& 定义, std::string& 释放) {
//	self->m_Code = "";
//	self->m_ReleaseCode = "";
//
//	std::string Color = "Color";
//	self->m_Code += "vec3 " + Color + " = f_MaterialPBR_calc(material, gl_WorldRayDirectionEXT, LigthDir, normal, hitValue);\n";
//	self->m_Code += "hitValue.Color = mix(hitValue.Color, " + Color + ", 0.6);\n";
//
//	self->f_get输出插座(1)->f_setCode(Color);
//
//	return self->m_Code;
//}

static void f_update着色器参数配置(S_材质管线* mat, S_物体* ob, S_Mesh* me, uint8 元素, uint32 多维子元素) {
	//S_面基本光照材质* sm = (S_面基本光照材质*)(mat);

	f_df_allocGPU参数缓存槽(&me->m_多维材质槽[多维子元素].m_参数槽, 18);

	me->m_多维材质槽[多维子元素].m_参数槽.m_参数槽[2] = &ob->m_实例颜色[元素];
	me->m_多维材质槽[多维子元素].m_参数槽.m_绑定位置[2] = DEF_BINDING_WIDGET_Color;
	me->m_多维材质槽[多维子元素].m_参数槽.m_参数类型[2] = E_板载缓存类型::e_SSBO;
	me->m_多维材质槽[多维子元素].m_参数槽.m_绑定数量[2] = 1;

	f_update着色器_骨骼配置(ob, me, 多维子元素, 3);

	me->m_多维材质槽[多维子元素].m_参数槽.m_参数槽[6] = &me->m_网格元素变换属性;
	me->m_多维材质槽[多维子元素].m_参数槽.m_绑定位置[6] = DEF_BINDING_LineProp;
	me->m_多维材质槽[多维子元素].m_参数槽.m_参数类型[6] = E_板载缓存类型::e_SSBO;
	me->m_多维材质槽[多维子元素].m_参数槽.m_绑定数量[6] = 1;

	me->m_多维材质槽[多维子元素].m_参数槽.m_参数槽[7] = &f_buf_getGlobal().g_全局绑定参数;
	me->m_多维材质槽[多维子元素].m_参数槽.m_绑定位置[7] = DEF_BINDING_Render_GlobalParam;
	me->m_多维材质槽[多维子元素].m_参数槽.m_参数类型[7] = E_板载缓存类型::e_SSBO;
	me->m_多维材质槽[多维子元素].m_参数槽.m_绑定数量[7] = 1;

	me->m_多维材质槽[多维子元素].m_参数槽.m_参数槽[8] = &f_buf_getGlobal().m_材质;
	me->m_多维材质槽[多维子元素].m_参数槽.m_绑定位置[8] = DEF_MaterialsBindID;
	me->m_多维材质槽[多维子元素].m_参数槽.m_参数类型[8] = E_板载缓存类型::e_SSBO;
	me->m_多维材质槽[多维子元素].m_参数槽.m_绑定数量[8] = 1;


	me->m_多维材质槽[多维子元素].m_参数槽.m_参数槽[9] = me->m_面;
	me->m_多维材质槽[多维子元素].m_参数槽.m_绑定位置[9] = DEF_BINDING_TasterBindID_Face;
	me->m_多维材质槽[多维子元素].m_参数槽.m_参数类型[9] = E_板载缓存类型::e_SSBO;
	me->m_多维材质槽[多维子元素].m_参数槽.m_绑定数量[9] = 1;

	me->m_多维材质槽[多维子元素].m_参数槽.m_参数槽[10] = me->m_UV;
	me->m_多维材质槽[多维子元素].m_参数槽.m_绑定位置[10] = DEF_BINDING_TasterBindID_TexCoord;
	me->m_多维材质槽[多维子元素].m_参数槽.m_参数类型[10] = E_板载缓存类型::e_SSBO;
	me->m_多维材质槽[多维子元素].m_参数槽.m_绑定数量[10] = 1;

	me->m_多维材质槽[多维子元素].m_参数槽.m_参数槽[11] = me->m_UV索引;
	me->m_多维材质槽[多维子元素].m_参数槽.m_绑定位置[11] = DEF_BINDING_TasterBindID_TexIndex;
	me->m_多维材质槽[多维子元素].m_参数槽.m_参数类型[11] = E_板载缓存类型::e_SSBO;
	me->m_多维材质槽[多维子元素].m_参数槽.m_绑定数量[11] = 1;


	me->m_多维材质槽[多维子元素].m_参数槽.m_参数槽[12] = me->m_自定义属性索引;
	me->m_多维材质槽[多维子元素].m_参数槽.m_绑定位置[12] = DEF_BINDING_Face_AttrIndex;
	me->m_多维材质槽[多维子元素].m_参数槽.m_参数类型[12] = E_板载缓存类型::e_SSBO;
	me->m_多维材质槽[多维子元素].m_参数槽.m_绑定数量[12] = 1;

	me->m_多维材质槽[多维子元素].m_参数槽.m_参数槽[13] = &me->m_多维材质槽[多维子元素].m_Material->m_材质自定义属性索引;
	me->m_多维材质槽[多维子元素].m_参数槽.m_绑定位置[13] = DEF_BINDING_Material_AttrIndex;
	me->m_多维材质槽[多维子元素].m_参数槽.m_参数类型[13] = E_板载缓存类型::e_SSBO;
	me->m_多维材质槽[多维子元素].m_参数槽.m_绑定数量[13] = 1;
	
	me->m_多维材质槽[多维子元素].m_参数槽.m_参数槽[14] = me->m_网格属性;
	me->m_多维材质槽[多维子元素].m_参数槽.m_绑定位置[14] = DEF_BINDING_ObMesh;
	me->m_多维材质槽[多维子元素].m_参数槽.m_参数类型[14] = E_板载缓存类型::e_SSBO;
	me->m_多维材质槽[多维子元素].m_参数槽.m_绑定数量[14] = 1;

	me->m_多维材质槽[多维子元素].m_参数槽.m_参数槽[15] = &f_buf_getGlobal().g_透明链表计数;
	me->m_多维材质槽[多维子元素].m_参数槽.m_绑定位置[15] = DEF_TasterBindID_AlphaListCount;
	me->m_多维材质槽[多维子元素].m_参数槽.m_参数类型[15] = E_板载缓存类型::e_SSBO;
	me->m_多维材质槽[多维子元素].m_参数槽.m_绑定数量[15] = 1;

	me->m_多维材质槽[多维子元素].m_参数槽.m_参数槽[16] = f_buf_getGlobal().g_透明链表纹理;
	me->m_多维材质槽[多维子元素].m_参数槽.m_绑定位置[16] = DEF_TasterTexturesBindID_rgba32ui;
	me->m_多维材质槽[多维子元素].m_参数槽.m_参数类型[16] = E_板载缓存类型::e_图像缓存;
	me->m_多维材质槽[多维子元素].m_参数槽.m_绑定数量[16] = 1;
	
	me->m_多维材质槽[多维子元素].m_参数槽.m_参数槽[17] = f_buf_getGlobal().g_透明链表头;
	me->m_多维材质槽[多维子元素].m_参数槽.m_绑定位置[17] = DEF_TasterTexturesBindID_r32ui;
	me->m_多维材质槽[多维子元素].m_参数槽.m_参数类型[17] = E_板载缓存类型::e_IMAGE;
	me->m_多维材质槽[多维子元素].m_参数槽.m_绑定数量[17] = 1;
	


	me->m_多维材质槽[多维子元素].m_参数槽.m_纹理槽 = &f_buf_getGlobal().g_全局模型纹理槽;
}


static std::string f_着色器纹理定义() {
	std::string shader_code;
	
	shader_code += "layout(binding = DEF_TasterTexturesBindID_rgba8) uniform sampler2D Ts[]; \n";
	//shader_code += "layout(binding = DEF_TasterTexturesBindID_rgba8, rgba8) uniform sampler2D Ts[]; \n";
	//shader_code += "layout(binding = DEF_TasterTexturesBindID_rgba32f, rgba32f) uniform image2D Ts_rgba32f[]; \n";
	return shader_code;
}


static std::string f_光追回调着色器引入() {
	std::string shader_code;

	shader_code += "#version 460 core\n";
	shader_code += "#extension GL_EXT_ray_tracing : require\n";
	shader_code += "#extension GL_EXT_scalar_block_layout : enable\n";
	shader_code += "#extension GL_EXT_nonuniform_qualifier : enable\n";
	shader_code += "#extension GL_EXT_buffer_reference2 : require\n";
	shader_code += "#extension GL_EXT_shader_explicit_arithmetic_types_int64 : require\n";
	shader_code += "#extension GL_GOOGLE_include_directive : enable\n";

	shader_code += "#include \"shader_std.h\" \n";
	shader_code += "#include \"shader_ray.h\" \n";
	shader_code += "#include \"shader_built_in_functions.h\" \n";

	shader_code += "#include \"shader_PBR.h\"\n";
	shader_code += "#include \"shader_rcall.h\"\n";
	shader_code += "#include \"shader_ob.h\"\n";
	shader_code += "#include \"shader_texture.h\"\n";
	shader_code += "#include \"shader_sample.h\"\n";
	shader_code += "#include \"shader_noise.h\"\n";
	//shader_code += "#extension GL_EXT_debug_printf : enable\n";

	shader_code += "layout(binding = DEF_RenderFrameBindID, set = 0, scalar) uniform FrameProp { GLSL_RenderFrame renderFrame; };\n";

	return shader_code;
}

static std::string f_几何着色器扩展头文件() {
	std::string shader_code;

	shader_code += "#version 460 core\n";
	shader_code += "#extension GL_GOOGLE_include_directive : enable\n";
	shader_code += "#extension GL_EXT_scalar_block_layout : enable\n";
	shader_code += "#extension GL_EXT_nonuniform_qualifier : enable\n";
	shader_code += "#extension GL_EXT_buffer_reference2 : require\n";
	shader_code += "#extension GL_EXT_shader_explicit_arithmetic_types_int64 : require\n";

	shader_code += "#include \"shader_binding_ID.h\" \n";
	shader_code += "#include \"shader_ray.h\" \n";
	shader_code += "#include \"shader_std.h\" \n";
	shader_code += "#include \"shader_mesh.h\" \n";
	shader_code += "#include \"shader_taster_geomFaceAttr.h\" \n";


	shader_code += "layout(triangles) in; \n";
	shader_code += "layout(triangle_strip, max_vertices = 64) out;\n";
	//shader_code += "layout(line_strip, max_vertices = 12) out; \n";

	return shader_code;
}



static std::string f_片源着色器引入() {
	std::string shader_code;

	shader_code += "#version 460 core\n";
	shader_code += "#extension GL_GOOGLE_include_directive : enable\n";
	shader_code += "#extension GL_EXT_scalar_block_layout : enable\n";
	shader_code += "#extension GL_EXT_nonuniform_qualifier : enable\n";
	shader_code += "#extension GL_EXT_buffer_reference2 : require\n";
	//shader_code += "#extension GL_EXT_shader_atomic : enable\n";
	shader_code += "#extension GL_EXT_shader_explicit_arithmetic_types_int64 : require\n";
	
	shader_code += "#include \"shader_std.h\" \n";
	shader_code += "#include \"shader_ray.h\" \n";
	shader_code += "#include \"shader_built_in_functions.h\" \n";
	
	shader_code += "#include \"shader_curve.h\" \n";

	//shader_code += "layout(early_fragment_tests) in;\n";
	shader_code += "layout(buffer_reference, scalar) readonly buffer R_GlobalParameter { S_GlobalParam GlobalParamAddress[]; };\n";
	shader_code += "layout(buffer_reference, scalar) readonly buffer R_GlobalParameter_CurevPoint { S_CurvePoint  curvePointPtr[]; };\n";
	
	shader_code += "layout(binding = DEF_BINDING_Render_GlobalParam, scalar) readonly buffer B_GlobalParam { S_GlobalParam gGlobalParam; };\n";
	shader_code += "layout(binding = DEF_MaterialsBindID, scalar) readonly buffer B_Material { S_Material m_Material[]; };\n";
	shader_code += "layout(binding = DEF_BINDING_MeshFaceID, scalar) readonly buffer B_ObMesh { S_ObMesh m_ObMesh[]; };\n";
	shader_code += "layout(binding = DEF_BINDING_TasterBindID_TexCoord, scalar) readonly buffer B_TexCoord { vec2 m_TexCoord[]; };\n";
	shader_code += "layout(binding = DEF_BINDING_TasterBindID_TexIndex, scalar) readonly buffer B_TexIndex { uvec3 m_TexIndex[]; };\n";
	shader_code += "layout(binding = DEF_BINDING_Face_AttrIndex, scalar) readonly buffer Face_CustomAttr { S_CustomAttr CustomAttrPtr[]; } customAttr_GParam;\n";
	shader_code += "layout(binding = DEF_BINDING_Material_AttrIndex, scalar) readonly buffer Material_CustomAttr { S_CustomAttr CustomAttrPtr[]; } MaterialCA_GParam;\n";


	shader_code += "#include \"shader_PBR.h\"\n";
	shader_code += "#include \"shader_texture.h\"\n";
	shader_code += "#include \"shader_sample.h\"\n";
	shader_code += "#include \"shader_noise.h\"\n";
	

	shader_code += "layout(location = DEF_BINDING_LocationBindID_Vert) in vec3 vVert;\n";
	shader_code += "layout(location = DEF_BINDING_TasterBindID_MaterialID) in flat S_FaceAttr Element;\n";
	//shader_code += "layout(location = DEF_BINDING_TasterBindID_FaceAttr) out S_Geom_MeshDrawProp vFaceAttr\"\n";
	//shader_code += "layout(location = DEF_BINDING_TasterBindID_RotMat) out mat4 vTranformMat\"\n";
	shader_code += "layout(location = 8) in flat uint inPrimitiveID;\n";
	shader_code += "layout(location = 9) in flat uint gMeshOffset;\n";
	shader_code += "layout(location = 10) in vec3 inBarycentrics;\n";
	shader_code += "layout(location = 11) in vec2 outUV[4];\n";


	//shader_code += "layout(binding = DEF_TasterTexturesBindID_rgba32ui, rgba32ui) uniform uimage1D Ts_rgba32ui; \n";
	shader_code += "layout(binding = DEF_TasterTexturesBindID_rgba32ui) buffer B_RGBA32UI { uvec4 ListPix[]; };\n";
	shader_code += "layout(binding = DEF_TasterTexturesBindID_r32ui, r32ui) restrict uniform uimage2D ListPix_Pointer; \n";
	shader_code += "layout(binding = DEF_TasterBindID_AlphaListCount) restrict writeonly buffer B_COUNT{ uint ListPix_count[]; };\n";
	//shader_code += "layout(binding = DEF_TasterBindID_AlphaListCount) uniform atomic_uint ListPix_count; \n";

	shader_code += f_着色器纹理定义();

	return shader_code;
}

static std::string f_几何着色器参数引入(bool 优化 = false) {
	std::string shader_code;

	shader_code += "layout(location = 0) in vec4 vColor[];\n";
	shader_code += "layout(location = 1) in vec3 vNormal[];\n";
	shader_code += "layout(location = 2) in vec3 vCamera[][4];\n";
	//shader_code += "layout(location = 6) in float DepthScale[];\n";
	shader_code += "layout(location = 8) in uint vVertIndexID[];\n";
	shader_code += "layout(location = 9) in uint vMeshOffset[];\n";
	shader_code += "layout(location = 20) in uint vFaceOffset[];\n";

	shader_code += "layout(location = DEF_BINDING_LocationBindID_Vert) in vec3 vVert[];\n";
	shader_code += "layout(location = DEF_BINDING_LocationBindID_FaceAttr) in S_Geom_MeshDrawProp vFaceAttr[];\n";
	shader_code += "layout(location = DEF_BINDING_LocationBindID_RotMat) in mat4 vTranformMat[];\n";
	


	shader_code += "layout(binding = DEF_BINDING_ObMesh, scalar) readonly buffer B_ObMesh { S_ObMesh ObMesh[]; };\n";
	shader_code += "layout(binding = DEF_BINDING_TasterBindID_Face, scalar) readonly buffer B_Faces { S_FaceElement m_Face[]; };\n";
	shader_code += "layout(binding = DEF_BINDING_Render_GlobalParam, scalar) readonly buffer B_GlobalParam { S_GlobalParam gGlobalParam; };\n";
	
	shader_code += "layout(binding = DEF_BINDING_Face_AttrIndex, scalar) readonly buffer Face_CustomAttr { S_CustomAttr CustomAttrPtr[]; } customAttr_GParam;\n";
	shader_code += "layout(binding = DEF_BINDING_Material_AttrIndex, scalar) readonly buffer Material_CustomAttr { S_CustomAttr CustomAttrPtr[]; } MaterialCA_GParam;\n";


	shader_code += "in gl_PerVertex{\n";
	shader_code += "	vec4 gl_Position;\n";
	shader_code += "	float gl_PointSize;\n";
	shader_code += "}gl_in[];\n";

	shader_code += "out gl_PerVertex{\n";
	shader_code += "	vec4 gl_Position;\n";
	shader_code += "};\n";


	shader_code += "layout(location = 0) out vec4 outColor;\n";
	shader_code += "layout(location = 1) out vec3 outNormal;\n";
	shader_code += "layout(location = 2) out vec3 outCamera[4];\n";
	//shader_code += "layout(location = 6) out float outDepthScale;\n";
	shader_code += "layout(location = 8) out uint outPrimitiveID;\n";
	shader_code += "layout(location = 9) out uint outMeshOffset;\n";
	shader_code += "layout(location = 10) out vec3 outBarycentrics;\n";
	shader_code += "layout(location = 11) out vec2 outUV[4];\n";

	shader_code += "layout(location = DEF_BINDING_LocationBindID_Vert) out vec3 gVert;\n";
	shader_code += "layout(location = DEF_BINDING_TasterBindID_MaterialID) out flat S_FaceAttr Element;\n";

	shader_code += "uint inPrimitiveID;\n";

	return shader_code;
}

static std::string f_几何着色轮廓边生成代码构建() {
	std::string shader_code;

	std::string 摄像机 = "outCamera[0] = vCamera[0][0];\n outCamera[1] = vCamera[0][1];\n outCamera[2] = vCamera[0][2];\n outCamera[3] = vCamera[0][3];\n";
	std::string 面代码 = "Element.MaterialID = face.MaterialID;\n";
				面代码 += "Element.MaterialSlot = face.MaterialSlot; \n ";
				面代码 += "Element.Offset_MeshAttr = vFaceAttr[0].Offset_MeshAttr;\n ";
				面代码 += "Element.Offset_MaterialAttr = vFaceAttr[0].Offset_MaterialAttr;\n ";
				面代码 += "outPrimitiveID = inPrimitiveID;\n ";

	shader_code += "vec3 edgeA = (vVert[1] - vVert[0]);\n";
	shader_code += "vec3 edgeB = (vVert[2] - vVert[0]);\n";
	shader_code += "vec3 edgeC = (vVert[1] - vVert[2]);\n";
	shader_code += "vec3 Normal = normalize(cross(edgeA, edgeB));\n";

	shader_code += "S_Geom_MeshDrawProp AttrOffset = vFaceAttr[0];\n";
	shader_code += "vec3 Co = (vVert[0] + vVert[1] + vVert[2]) / 3;\n";

	shader_code += "uvec3 AdjacencyID = g_Face_AdjacencyID[AttrOffset.Offset_Face_AdjacencyID + inPrimitiveID];\n";
	shader_code += "uvec3 NormalAID = AdjacencyID + AttrOffset.Offset_Face_Normal;\n";
	shader_code += "uvec3 CenterAID = AdjacencyID + AttrOffset.Offset_Face_Center;\n";

	shader_code += "mat3 normalMat = mat3(vTranformMat[0]);\n";
	shader_code += "vec3 viewLine = vCamera[0][1] - (vTranformMat[0] * vec4(Co, 1)).xyz ;\n";
	shader_code += "float nv = dot(normalMat * Normal, viewLine);\n";

	
	shader_code += "if (nv <= 0) return;\n";
	
	shader_code += "viewLine = vCamera[0][1] - (vTranformMat[0] * vec4(g_Face_Center[CenterAID.x], 1)).xyz;\n";
	//shader_code += "viewLine = normalMat * Normal;\n";
	//shader_code += "Normal = viewLine;\n";
	//shader_code += "Normal = vec3( greaterThan(AdjacencyID, uvec3(0)) );\n";
	
	//shader_code += "NormalAID = uvec3(0);\n";
	shader_code += "if (dot(viewLine, normalMat * g_Face_Normal[NormalAID.x]) <= 0.0) {\n";
	//shader_code += "for(int i=0; i<6; ++i){\n";
	//shader_code += "}\n";

	shader_code += "	outColor = vColor[0];\n";
	shader_code += "	outNormal = Normal;\n";
	shader_code += "	gVert = vVert[0];\n";
	//shader_code += "	Element = m_Face[vFaceAttr[0].Offset_Face + primitiveID];\n";
	shader_code += 面代码;
	shader_code += 摄像机;
	shader_code += "	gl_Position = gl_in[0].gl_Position;\n";
	shader_code += "	EmitVertex();\n";

	shader_code += "	outColor = vColor[1];\n";
	shader_code += "	outNormal = Normal;\n";
	shader_code += "	gVert = vVert[1];\n";
	//shader_code += "	Element = m_Face[vFaceAttr[1].Offset_Face + primitiveID];\n";
	shader_code += 面代码;
	shader_code += 摄像机;
	shader_code += "	gl_Position = gl_in[1].gl_Position;\n";
	shader_code += "	EmitVertex();\n";
	shader_code += "	EndPrimitive();\n";

	shader_code += "}\n";
	//shader_code += "return;\n";
	shader_code += "viewLine = vCamera[0][1] - (vTranformMat[1] * vec4(g_Face_Center[CenterAID.y], 1)).xyz;\n";
	shader_code += "if (dot(viewLine, normalMat * g_Face_Normal[NormalAID.y]) <= 0.0) {\n";

	shader_code += "	outColor = vColor[1];\n";
	shader_code += "	outNormal = Normal;\n";
	shader_code += "	gVert = vVert[1];\n";
	//shader_code += "	Element = m_Face[vFaceAttr[1].Offset_Face + primitiveID];\n";
	shader_code += 面代码;
	shader_code += 摄像机;
	shader_code += "	gl_Position = gl_in[1].gl_Position;\n";
	shader_code += "	EmitVertex();\n";

	shader_code += "	outColor = vColor[2];\n";
	shader_code += "	outNormal = Normal;\n";
	shader_code += "	gVert = vVert[2];\n";
	//shader_code += "	Element = m_Face[vFaceAttr[2].Offset_Face + primitiveID];\n";
	shader_code += 面代码;
	shader_code += 摄像机;
	shader_code += "	gl_Position = gl_in[2].gl_Position;\n";
	shader_code += "	EmitVertex();\n";
	shader_code += "	EndPrimitive();\n";

	shader_code += "}\n";

	shader_code += "viewLine = vCamera[0][1] - (vTranformMat[2] * vec4(g_Face_Center[CenterAID.z], 1)).xyz;\n";
	shader_code += "if (dot(viewLine, normalMat * g_Face_Normal[NormalAID.z]) <= 0.0) {\n";

	shader_code += "	outColor = vColor[2];\n";
	shader_code += "	outNormal = Normal;\n";
	shader_code += "	gVert = vVert[2];\n";
	//shader_code += "	Element = m_Face[vFaceAttr[2].Offset_Face + primitiveID];\n";
	shader_code += 面代码;
	shader_code += 摄像机;
	shader_code += "	gl_Position = gl_in[2].gl_Position;\n";
	shader_code += "	EmitVertex();\n";

	shader_code += "	outColor = vColor[0];\n";
	shader_code += "	outNormal = Normal;\n";
	shader_code += "	gVert = vVert[0];\n";
	//shader_code += "	Element = m_Face[vFaceAttr[0].Offset_Face + primitiveID];\n";
	shader_code += 面代码;
	shader_code += 摄像机;
	shader_code += "	gl_Position = gl_in[0].gl_Position;\n";
	shader_code += "	EmitVertex();\n";
	shader_code += "	EndPrimitive();\n";

	shader_code += "}\n";

	return shader_code;
}


static std::string f_着色器自定义全局属性() {
	std::string code;

	code += "R_GlobalParameter_I32   CAP_i32_GParam   = R_GlobalParameter_I32(gGlobalParam.m_AddressCustomAttrP_I32);\n";
	code += "R_GlobalParameter_UI32  CAP_ui32_GParam  = R_GlobalParameter_UI32(gGlobalParam.m_AddressCustomAttrP_UI32);\n";
	code += "R_GlobalParameter_F32   CAP_f32_GParam   = R_GlobalParameter_F32(gGlobalParam.m_AddressCustomAttrP_F32);\n";
	code += "R_GlobalParameter_Vec2  CAP_vec2_GParam  = R_GlobalParameter_Vec2(gGlobalParam.m_AddressCustomAttrP_Vec2);\n";
	code += "R_GlobalParameter_Vec3  CAP_vec3_GParam  = R_GlobalParameter_Vec3(gGlobalParam.m_AddressCustomAttrP_Vec3);\n";
	code += "R_GlobalParameter_Vec4  CAP_vec4_GParam  = R_GlobalParameter_Vec4(gGlobalParam.m_AddressCustomAttrP_Vec4);\n";
	code += "R_GlobalParameter_iVec2 CAP_ivec2_GParam = R_GlobalParameter_iVec2(gGlobalParam.m_AddressCustomAttrP_iVec2);\n";
	code += "R_GlobalParameter_iVec3 CAP_ivec3_GParam = R_GlobalParameter_iVec3(gGlobalParam.m_AddressCustomAttrP_iVec3);\n";
	code += "R_GlobalParameter_iVec4 CAP_ivec4_GParam = R_GlobalParameter_iVec4(gGlobalParam.m_AddressCustomAttrP_iVec4);\n";

	code += "R_GlobalParameter_I32   CAF_i32_GParam   = R_GlobalParameter_I32(gGlobalParam.m_AddressCustomAttrF_I32);\n";
	code += "R_GlobalParameter_UI32  CAF_ui32_GParam  = R_GlobalParameter_UI32(gGlobalParam.m_AddressCustomAttrF_UI32);\n";
	code += "R_GlobalParameter_F32   CAF_f32_GParam   = R_GlobalParameter_F32(gGlobalParam.m_AddressCustomAttrF_F32);\n";
	code += "R_GlobalParameter_Vec2  CAF_vec2_GParam  = R_GlobalParameter_Vec2(gGlobalParam.m_AddressCustomAttrF_Vec2);\n";
	code += "R_GlobalParameter_Vec3  CAF_vec3_GParam  = R_GlobalParameter_Vec3(gGlobalParam.m_AddressCustomAttrF_Vec3);\n";
	code += "R_GlobalParameter_Vec4  CAF_vec4_GParam  = R_GlobalParameter_Vec4(gGlobalParam.m_AddressCustomAttrF_Vec4);\n";
	code += "R_GlobalParameter_iVec2 CAF_ivec2_GParam = R_GlobalParameter_iVec2(gGlobalParam.m_AddressCustomAttrF_iVec2);\n";
	code += "R_GlobalParameter_iVec3 CAF_ivec3_GParam = R_GlobalParameter_iVec3(gGlobalParam.m_AddressCustomAttrF_iVec3);\n";
	code += "R_GlobalParameter_iVec4 CAF_ivec4_GParam = R_GlobalParameter_iVec4(gGlobalParam.m_AddressCustomAttrF_iVec4);\n";

	return code;
}


static std::string f_偏移着色器透明链表代码构建(const std::string& 混合方式) {
	std::string shader_code;
	//shader_code += "uint index = atomicCounterIncrement(ListPix_count[1]);\n";
	//shader_code += "uint head_index = imageAtomicExchange(ListPix_Pointer, ivec2(gl_FragCoord.xy), 1);\n";

	//shader_code += "ListPix[index] = uvec4(head_index, packUnorm4x8(vec4(vec2(gl_FragCoord)*0.0001, 0, 1)), floatBitsToUint(gl_FragCoord.z), 1);\n";
	
	//shader_code += "uint sampleMask = uint(1) << gl_SampleID;\n";
	shader_code += "if(outColor.a > 0){\n";
	//shader_code += "vec4 sampleColor = vec4(0);\n";
	//shader_code += "for(int i=0; i<4; ++i){\n";
	//shader_code += "	sampleColor += outColor * (0.7 - length(gl_SamplePosition[i] - vec2(0.5)));\n";
	//shader_code += "}\n";
	//shader_code += "outColor = sampleColor / 4;\n";
	//shader_code += "outColor = vec4(vec2(gl_SamplePosition[gl_SampleID]),0,1);\n";
	//shader_code += "	outColor = vec4( vec3(length(gl_SamplePosition - vec2(0.5))), 1 );\n";
	//shader_code += "outColor = vec4( vec3(gl_SamplePosition[gl_SampleID].x, gl_SamplePosition[gl_SampleID], 0), 1 );\n";


	//shader_code += "vec2 sp = gl_SamplePosition; \n";
	//shader_code += "outColor.a *= 0.25;\n";
	
	//shader_code += "if(gl_SampleID == 0) outColor = vec4(1,0,0,1);\n";
	//shader_code += "if(gl_SampleID == 1) outColor = vec4(0,1,0,1);\n";
	//shader_code += "if(gl_SampleID == 2) outColor = vec4(0,0,1,1);\n";
	//shader_code += "if(gl_SampleID == 3) outColor = vec4(1,0,1,1);\n";

	shader_code += "	uint index = atomicAdd(ListPix_count[0], 1);\n";
	shader_code += "	uint head_index = imageAtomicExchange(ListPix_Pointer, ivec2(gl_FragCoord.xy), index);\n";
	//shader_code += "	ListPix[index] = uvec4(head_index, packUnorm4x8(outColor), floatBitsToUint(gl_FragCoord.z), packUnorm4x8(vec4(vNormal, " + 混合方式 + "&0x000000ff)));\n";
	shader_code += "	ListPix[index] = uvec4(head_index, packUnorm4x8(outColor), floatBitsToUint(gl_FragCoord.z), packUnorm4x8(vec4(vNormal, 0)) | (uint(" + 混合方式 + ")<<24) );\n";
	//shader_code += "	ListPix[index] = uvec4(head_index, packUnorm4x8(outColor), floatBitsToUint(gl_FragDepth), 1);\n";
	shader_code += "}\n";
	return shader_code;
}




static std::string f_网格自定义属性定义(bool 光追 = true) {
	std::string code;
	if (光追) {
		code += "R_GlobalParameter_CustomAttr customAttr_GParam = R_GlobalParameter_CustomAttr(Resource_ObMesh.m_CustomAttrOffset);\n";
		code += "R_GlobalParameter_CustomAttr MaterialCA_GParam = R_GlobalParameter_CustomAttr(material.m_CustomAttrOffset);\n";

		code += "R_GlobalParameter_CustomAttr customObInstanceAttr_GParam = R_GlobalParameter_CustomAttr(rtOb.m_Address_InstanceAttrIndex);\n";
	}
	else {
		//code += "layout(binding = DEF_BINDING_Material_AttrIndex, scalar) readonly buffer Material_CustomAttr { S_CustomAttr m_CustomAttr[]; } MaterialCA_GParam;\n";
		//code += "layout(binding = DEF_BINDING_Face_AttrIndex, scalar) readonly buffer Face_CustomAttr { S_CustomAttr m_CustomAttr[]; } customAttr_GParam;\n";
	}
	
	return code;
}
//static std::string f_几何着色器网格属性定义() {
//	std::string code;
//	//code += "S_ObMesh		Resource_ObMesh = m_ObMesh[vMeshOffset[0]];\n";
//	//code += "B_Faces		mesh_face       = B_Faces(Resource_ObMesh.m_AddressFaces);\n";
//	code += "S_FaceElement	face			= m_Face[vFaceAttr[0].Offset_Face + primitiveID];\n";
//	//code += "Element = m_Face[vFaceAttr[0].Offset_Face + primitiveID];\n";
//	code += "Element.MaterialID = face.MaterialID;\n";
//	code += "Element.MaterialSlot = face.MaterialSlot;\n";
//	code += "Element.Offset_MeshAttr = vFaceAttr[0].Offset_MeshAttr;\n";
//	code += "Element.Offset_MaterialAttr = vFaceAttr[0].Offset_MaterialAttr;\n";
//	
//	code += f_网格自定义属性定义(false);
//	return code;
//}

static std::string f_像素着色器网格属性定义() {
	std::string code;

	//code += "S_ObMesh		Resource_ObMesh = m_ObMesh[gMeshOffset];\n";
	//code += "B_Faces		mesh_face       = B_Faces(Resource_ObMesh.m_AddressFaces);\n";
	//code += "S_FaceElement	Element			= mesh_face.Element[inPrimitiveID];\n";
	
	code += f_网格自定义属性定义(false);
	return code;
}

static std::string f_光追回调着色器引用数据声明() {
	std::string code;
	
	code += f_代码构建_着色器引用数据声明();

	//自定义属性变量;
	code += f_着色器自定义全局属性();

	code += "R_GlobalParameter_UI64 addressRtOb = R_GlobalParameter_UI64(renderFrame.m_Address_RtOb);\n";
	code += "S_RtOb rtOb                        = B_RtOb(addressRtOb.ui64Ptr[0]).gRtOb[callSceneData.InstanceIndex];\n";

	//code += "S_ObMesh      Resource_ObMesh = ObMesh.m_Address[callSceneData.InstanceIndex];\n";
	code += "S_ObMesh      Resource_ObMesh = ObMesh.m_Address[rtOb.m_AddressMesh];\n";

	code += "B_Indexs      mesh_vertIndex  = B_Indexs(Resource_ObMesh.m_AddressIndex);\n";
	code += "B_Indexs      mesh_uvIndex    = B_Indexs(Resource_ObMesh.m_AddressUVIndex);\n";
	code += "B_UV          mesh_uv         = B_UV(Resource_ObMesh.m_AddressUV);\n";
	code += "B_Faces       mesh_face       = B_Faces(Resource_ObMesh.m_AddressFaces);\n";

	code += "S_FaceElement	Element			= mesh_face.Element[callSceneData.PrimitiveIndex];\n";
	code += "S_Material		material		= m_Material[ callSceneData.MaterialID & 0x0000ffff ];\n";
	//code += "S_Material material           = m_Material[ 0 ];\n";
	code += f_网格自定义属性定义();
	//code += "R_GlobalParameter_CustomAttr customAttr_GParam = R_GlobalParameter_CustomAttr(Resource_ObMesh.m_CustomAttrOffset);\n";
	//code += "R_GlobalParameter_CustomAttr MaterialCA_GParam = R_GlobalParameter_CustomAttr(material.m_CustomAttrOffset);\n";
	
	return code;
}


static std::string f_片源着色器引用变量定义() {
	std::string code = f_代码构建_着色器引用数据声明();

	//自定义属性变量;
	code += f_着色器自定义全局属性();

	code += "S_Material material = m_Material[ Element.MaterialID ];\n";

	code += "callSceneData.Vert = vVert;\n";
	code += "callSceneData.Normal = vNormal;\n";
	code += "callSceneData.barycentrics = inBarycentrics;\n";
	code += "callSceneData.PrimitiveIndex = inPrimitiveID;\n";
	

	//code += "S_ObMesh Resource_ObMesh = ObMesh.m_Address[m_ObMesh[vMeshOffset[0]];\n";

	//code += f_网格自定义属性定义();
	//code += "R_GlobalParameter_CustomAttr MaterialCA_GParam = R_GlobalParameter_CustomAttr(material.m_CustomAttrOffset);\n";
	//code += "R_GlobalParameter_CustomAttr customAttr_GParam = R_GlobalParameter_CustomAttr(Resource_ObMesh.m_CustomAttrOffset);\n";
	//code += "S_FaceElement Element = m_Element[inPrimitiveID];\n";

	return code;
}


static void f_像素着色器节点输出节点插座(C_节点基类* node) {
	auto* socket1 = new C_Vec3插座(u"颜色");
	auto* socket2 = new C_F32插座(u"粗糙");
	auto* socket3 = new C_F32插座(u"不透明");

	auto* socket4 = new C_Vec3插座(u"法线");
	auto* socket5 = new C_Vec3插座(u"自发光颜色");
	auto* socket6 = new C_F32插座(u"自发光强度");

	auto* socket7 = new C_I32插座(u"混合模式");

	node->f_add插座(socket1, E_插座方向::e_插座Type_输入);
	node->f_add插座(socket2, E_插座方向::e_插座Type_输入);
	node->f_add插座(socket3, E_插座方向::e_插座Type_输入);

	node->f_add插座(socket4, E_插座方向::e_插座Type_输入);
	node->f_add插座(socket5, E_插座方向::e_插座Type_输入);
	node->f_add插座(socket6, E_插座方向::e_插座Type_输入);

	node->f_add插座(socket7, E_插座方向::e_插座Type_输入);

	DEF_Vec3插座数据(socket1) = {0.5f,0.5f,0.5f};
	DEF_F32插座数据(socket2) = 0.5;
	DEF_F32插座数据(socket3) = 1;

	DEF_Vec3插座数据(socket4) = { 0.5f,0.5f,0.5f };
	DEF_Vec3插座数据(socket5) = { 0.0f,0.0f,0.0f };
	DEF_F32插座数据(socket6) = 0;
}

static void f_几何着色器节点输出节点插座(C_节点基类* node) {
	auto* socket1 = new C_Vec4插座(u"顶点");
	auto* socket2 = new C_Vec3插座(u"法线");
	auto* socket3 = new C_颜色插座(u"颜色");
	auto* socket4 = new C_F32插座(u"线宽");


	node->f_add插座(socket1, E_插座方向::e_插座Type_输入);
	node->f_add插座(socket2, E_插座方向::e_插座Type_输入);
	node->f_add插座(socket3, E_插座方向::e_插座Type_输入);
	node->f_add插座(socket4, E_插座方向::e_插座Type_输入);

	DEF_Vec3插座数据(socket1) = { 0.5f,0.5f,0.5f };
	DEF_Vec3插座数据(socket2) = { 0.5f,0.5f,0.5f };
	DEF_颜色插座数据(socket3) = { 0.5f,0.5f,0.5f,1.0f };
	DEF_F32插座数据(socket4) = 0.1f;
	
}

static void f_着色器输出节点插座GPU参数绑定(std::vector<C_节点基类*>& outNodes) {
	for (auto& e : outNodes) {
		uint32 num = e->f_get输入插座数量();
		for (uint32 i = 1; i < num; ++i) {
			f_构建代码_构建GPU插座变量(*e->f_get输入插座(i));
		}
	}
}

static std::string f_光追回调着色器输出参数代码构建(std::vector<C_节点基类*>& outNodes, std::string& m_Code) {
	std::string shader_code;
	for (auto& e : outNodes) {
		auto* outSocket1 = e->f_get输入插座(1);
		auto* outSocket2 = e->f_get输入插座(2);
		auto* outSocket3 = e->f_get输入插座(3);
		auto* outSocket4 = e->f_get输入插座(4);
		auto* outSocket5 = e->f_get输入插座(5);
		auto* outSocket6 = e->f_get输入插座(6);
		auto* outSocket7 = e->f_get输入插座(7);

		shader_code += outSocket1->f_构建变量代码(0);
		shader_code += outSocket2->f_构建变量代码(0);
		shader_code += outSocket3->f_构建变量代码(0);

		shader_code += outSocket4->f_构建变量代码(0);
		shader_code += outSocket5->f_构建变量代码(0);
		shader_code += outSocket6->f_构建变量代码(0);

		shader_code += outSocket7->f_构建变量代码(0);



		shader_code += "callSceneData.Color = vec3("     + outSocket1->f_getCode(0) + ");\n";
		shader_code += "callSceneData.roughness = " + outSocket2->f_getCode(0) + ";\n";
		shader_code += "callSceneData.alpha = "		+ outSocket3->f_getCode(0) + ";\n";

		shader_code += "callSceneData.Normal = vec3("	+ outSocket4->f_getCode(0) + ");\n";
		shader_code += "callSceneData.Vert = vec3("		+ outSocket5->f_getCode(0) + ");\n";
		shader_code += "callSceneData.reflect = "	+ outSocket6->f_getCode(0) + ";\n";

		if (outSocket1->m_GPU缓存.m_Buf) {
			f_buf_Vec3_at(outSocket1->m_GPU缓存) = DEF_Vec3插座数据(outSocket1);
			f_buf_F32_at(outSocket2->m_GPU缓存) = DEF_F32插座数据(outSocket2);
			f_buf_F32_at(outSocket3->m_GPU缓存) = DEF_F32插座数据(outSocket3);

			f_buf_Vec3_at(outSocket4->m_GPU缓存) = DEF_Vec3插座数据(outSocket4);
			f_buf_Vec3_at(outSocket5->m_GPU缓存) = DEF_Vec3插座数据(outSocket5);
			f_buf_F32_at(outSocket6->m_GPU缓存) = DEF_F32插座数据(outSocket6);

		}
	}

	return shader_code;
}

static std::string f_几何着色器输出参数代码构建(std::vector<C_节点基类*>& outNodes, std::string& m_Code) {
	std::string shader_code;
	for (auto& e : outNodes) {
		auto* outSocket1 = e->f_get输入插座(1);
		auto* outSocket2 = e->f_get输入插座(2);
		auto* outSocket3 = e->f_get输入插座(3);
		auto* outSocket4 = e->f_get输入插座(4);

		shader_code += outSocket1->f_构建变量代码(0);
		shader_code += outSocket2->f_构建变量代码(0);
		shader_code += outSocket3->f_构建变量代码(0);
		shader_code += outSocket4->f_构建变量代码(0);



		shader_code += "_point[index] = (" + outSocket1->f_getCode(0) + ");\n";
		shader_code += "Normal = (" + outSocket2->f_getCode(0) + ");\n";
		shader_code += "_color[index] = (" + outSocket3->f_getCode(0) + ");\n";
		shader_code += "lineWidth[index] = (" + outSocket4->f_getCode(0) + ");\n";

		if (outSocket1->m_GPU缓存.m_Buf) {
			f_buf_Vec3_at(outSocket1->m_GPU缓存) = DEF_Vec3插座数据(outSocket1);
			f_buf_Vec3_at(outSocket2->m_GPU缓存) = DEF_Vec3插座数据(outSocket2);
			f_buf_Vec4_at(outSocket3->m_GPU缓存) = DEF_Vec4插座数据(outSocket3);
			f_buf_F32_at(outSocket4->m_GPU缓存) = DEF_F32插座数据(outSocket4);
		}
	}

	return shader_code;
}




static std::string f_着色器插值代码构建(const std::string& a, const std::string& b, const std::string& c) {
	return a + " * callSceneData.barycentrics.x + " + b + " * callSceneData.barycentrics.y + " + c + " * callSceneData.barycentrics.z";
}

std::string f_面和实例网格自定义着色器数据代码生成(C_插座基类* socket, S_网格自定义属性& 属性, const std::string& 属性变量名称, const std::string& 索引) {
	std::string 属性变量;
	switch (属性.m_Type) {
		case E_值类型::e_Type_I32: {
			属性变量 += "int custom_attr_i32" + 属性变量名称 + " = CAF_i32_GParam.i32Ptr[" + 索引 + "];\n";
			socket->f_setCode("custom_attr_i32" + 属性变量名称);
			break;
		}
		case E_值类型::e_Type_UI32: {
			属性变量 += "uint custom_attr_ui32" + 属性变量名称 + " = CAF_ui32_GParam.ui32Ptr[" + 索引 + "];\n";
			socket->f_setCode("custom_attr_ui32" + 属性变量名称);
			break;
		}
		case E_值类型::e_Type_F32: {
			属性变量 += "float custom_attr_f32" + 属性变量名称 + " = CAF_f32_GParam.f32Ptr[" + 索引 + "];\n";
			socket->f_setCode("custom_attr_f32" + 属性变量名称);
			break;
		}
		case E_值类型::e_Type_Vec2: {
			属性变量 += "vec2 custom_attr_vec2" + 属性变量名称 + " = CAF_vec2_GParam.vec2Ptr[" + 索引 + "];\n";
			socket->f_setCode("custom_attr_vec2" + 属性变量名称);
			break;
		}
		case E_值类型::e_Type_Vec3: {
			属性变量 += "vec3 custom_attr_vec3" + 属性变量名称 + " = CAF_vec3_GParam.vec3Ptr[" + 索引 + "];\n";
			socket->f_setCode("custom_attr_vec3" + 属性变量名称);
			break;
		}
		case E_值类型::e_Type_Vec4: {
			属性变量 += "vec4 custom_attr_vec4" + 属性变量名称 + " = CAF_vec4_GParam.vec4Ptr[" + 索引 + "];\n";
			socket->f_setCode("custom_attr_vec4" + 属性变量名称);
			break;
		}
		case E_值类型::e_Type_iVec2: {
			属性变量 += "ivec2 custom_attr_ivec2" + 属性变量名称 + " = CAF_ivec2_GParam.ivec2Ptr[" + 索引 + "];\n";
			socket->f_setCode("custom_attr_ivec2" + 属性变量名称);
			break;
		}
		case E_值类型::e_Type_iVec3: {
			属性变量 += "ivec3 custom_attr_ivec3" + 属性变量名称 + " = CAF_ivec3_GParam.ivec3Ptr[" + 索引 + "];\n";
			socket->f_setCode("custom_attr_ivec3" + 属性变量名称);
			break;
		}
		case E_值类型::e_Type_iVec4: {
			属性变量 += "ivec4 custom_attr_ivec4" + 属性变量名称 + " = CAF_ivec4_GParam.ivec4Ptr[" + 索引 + "];\n";
			socket->f_setCode("custom_attr_ivec4" + 属性变量名称);
			break;
		}
		default:
			break;
	}
	return 属性变量;
}

std::string f_网格自定义着色器数据代码生成(C_插座基类* socket, S_网格自定义属性& 属性, uint32 i, E_着色阶段 着色阶段) {
	std::string 属性变量;
	std::string 属性局部偏移 = f_整数值转字符串(属性.m_OffsetID);
	std::string 属性变量名称 = f_整数值转字符串(i);
	
	//std::string 属性变量偏移 = "uint(customAttr_GParam.CustomAttrPtr[Element.MaterialSlot * 32 + " + 属性局部偏移 + "].offset)";
	//std::string 属性变量数量 = "uint(customAttr_GParam.CustomAttrPtr[Element.MaterialSlot * 32 + " + 属性局部偏移 + "].num)";
	std::string 属性变量偏移;
	std::string 属性变量数量;

	std::string 槽内数量 = DEF_S(DEF_网格自定义属性槽数量);
	switch (着色阶段) {
		case E_着色阶段::e_几何着色: 
		case E_着色阶段::e_像素着色: {
			属性变量偏移 = "uint(customAttr_GParam.CustomAttrPtr[Element.Offset_MeshAttr + Element.MaterialSlot * " + 槽内数量 + " + " + 属性局部偏移 + "].offset)";
			属性变量数量 = "uint(customAttr_GParam.CustomAttrPtr[Element.Offset_MeshAttr + Element.MaterialSlot * " + 槽内数量 + " + " + 属性局部偏移 + "].num)";
			break;
		}
		default: {
			属性变量偏移 = "uint(customAttr_GParam.CustomAttrPtr[Element.MaterialSlot * " + 槽内数量 + " + " + 属性局部偏移 + "].offset)";
			属性变量数量 = "uint(customAttr_GParam.CustomAttrPtr[Element.MaterialSlot * " + 槽内数量 + " + " + 属性局部偏移 + "].num)";
			break;
		}
	}

	switch (属性.m_分布方式) {
		case DEF_ShaderAttrLayout_Point: {
			switch (着色阶段) {
				case E_着色阶段::e_像素着色:
				case E_着色阶段::e_几何着色: {
					auto 索引 = 属性变量数量 + " > 0 ? " + 属性变量偏移 + " + inPrimitiveID : 0";
					
					break;
				}
				default: {
					std::string 变量偏移;
					变量偏移 += "uvec3 CA_IndexA;\n";
					变量偏移 += "CA_IndexA.x = " + 属性变量数量 + " > 0 ? " + 属性变量偏移 + " + mesh_vertIndex.I[callSceneData.PrimitiveIndex].x : 0;\n";
					变量偏移 += "CA_IndexA.y = " + 属性变量数量 + " > 0 ? " + 属性变量偏移 + " + mesh_vertIndex.I[callSceneData.PrimitiveIndex].y : 0;\n";
					变量偏移 += "CA_IndexA.z = " + 属性变量数量 + " > 0 ? " + 属性变量偏移 + " + mesh_vertIndex.I[callSceneData.PrimitiveIndex].z : 0;\n";



					switch (属性.m_Type) {
						case E_值类型::e_Type_I32: {
							属性变量 += "int custom_attr_i32" + 属性变量名称 + " = 0;\n";

							属性变量 += "{\n";
							属性变量 += 变量偏移;
							属性变量 += "int custom_attr_i32_a = CAP_i32_GParam.i32Ptr[CA_IndexA.x];\n";
							属性变量 += "int custom_attr_i32_b = CAP_i32_GParam.i32Ptr[CA_IndexA.y];\n";
							属性变量 += "int custom_attr_i32_c = CAP_i32_GParam.i32Ptr[CA_IndexA.z];\n";

							属性变量 += "custom_attr_i32" + 属性变量名称 + " = int(" + f_着色器插值代码构建("custom_attr_i32_a", "custom_attr_i32_b", "custom_attr_i32_c") + ");\n";
							属性变量 += "}\n";

							socket->f_setCode("custom_attr_i32" + 属性变量名称);
							break;
						}
						case E_值类型::e_Type_UI32: {
							属性变量 += "uint custom_attr_ui32" + 属性变量名称 + " = 0;\n";
							属性变量 += "{\n";
							属性变量 += 变量偏移;
							属性变量 += "uint custom_attr_ui32_a = CAP_ui32_GParam.ui32Ptr[CA_IndexA.x];\n";
							属性变量 += "uint custom_attr_ui32_b = CAP_ui32_GParam.ui32Ptr[CA_IndexA.y];\n";
							属性变量 += "uint custom_attr_ui32_c = CAP_ui32_GParam.ui32Ptr[CA_IndexA.z];\n";

							属性变量 += "custom_attr_ui32" + 属性变量名称 + " = uint(" + f_着色器插值代码构建("custom_attr_ui32_a", "custom_attr_ui32_b", "custom_attr_ui32_c") + ");\n";
							属性变量 += "}\n";

							socket->f_setCode("custom_attr_ui32" + 属性变量名称);
							break;
						}
						case E_值类型::e_Type_F32: {
							属性变量 += "float custom_attr_f32" + 属性变量名称 + " = 1;\n";
							属性变量 += "{\n";
							属性变量 += 变量偏移;
							属性变量 += "float custom_attr_f32_a = CAP_f32_GParam.f32Ptr[CA_IndexA.x];\n";
							属性变量 += "float custom_attr_f32_b = CAP_f32_GParam.f32Ptr[CA_IndexA.y];\n";
							属性变量 += "float custom_attr_f32_c = CAP_f32_GParam.f32Ptr[CA_IndexA.z];\n";

							属性变量 += "custom_attr_f32" + 属性变量名称 + " = " + f_着色器插值代码构建("custom_attr_f32_a", "custom_attr_f32_b", "custom_attr_f32_c") + ";\n";
							//属性变量 += "custom_attr_f32" + 属性变量名称 + " = " + f_着色器插值代码构建("float(CA_IndexA.x) * 0.03", "float(CA_IndexA.y) * 0.03", "float(CA_IndexA.z) * 0.03") + ";\n";
							属性变量 += "}\n";

							socket->f_setCode("custom_attr_f32" + 属性变量名称);
							break;
						}
						case E_值类型::e_Type_Vec2: {
							属性变量 += "vec2 custom_attr_vec2" + 属性变量名称 + " = vec2(0);\n";
							属性变量 += "{\n";
							属性变量 += 变量偏移;
							属性变量 += "vec2 custom_attr_vec2_a = CAP_vec2_GParam.vec2Ptr[CA_IndexA.x];\n";
							属性变量 += "vec2 custom_attr_vec2_b = CAP_vec2_GParam.vec2Ptr[CA_IndexA.y];\n";
							属性变量 += "vec2 custom_attr_vec2_c = CAP_vec2_GParam.vec2Ptr[CA_IndexA.z];\n";

							属性变量 += "custom_attr_vec2" + 属性变量名称 + " = " + f_着色器插值代码构建("custom_attr_vec2_a", "custom_attr_vec2_b", "custom_attr_vec2_c") + ";\n";
							属性变量 += "}\n";

							socket->f_setCode("custom_attr_vec2" + 属性变量名称);
							break;
						}
						case E_值类型::e_Type_Vec3: {
							属性变量 += "vec3 custom_attr_vec3" + 属性变量名称 + " = vec3(0);\n";
							属性变量 += "{\n";
							属性变量 += 变量偏移;
							属性变量 += "vec3 custom_attr_vec3_a = CAP_vec3_GParam.vec3Ptr[CA_IndexA.x];\n";
							属性变量 += "vec3 custom_attr_vec3_b = CAP_vec3_GParam.vec3Ptr[CA_IndexA.y];\n";
							属性变量 += "vec3 custom_attr_vec3_c = CAP_vec3_GParam.vec3Ptr[CA_IndexA.z];\n";

							属性变量 += "custom_attr_vec3" + 属性变量名称 + " = " + f_着色器插值代码构建("custom_attr_vec3_a", "custom_attr_vec3_b", "custom_attr_vec3_c") + ";\n";
							属性变量 += "}\n";

							socket->f_setCode("custom_attr_vec3" + 属性变量名称);
							break;
						}
						case E_值类型::e_Type_Vec4: {
							属性变量 += "vec4 custom_attr_vec4" + 属性变量名称 + " = vec4(0);\n";
							属性变量 += "{\n";
							属性变量 += 变量偏移;
							属性变量 += "vec4 custom_attr_vec4_a = CAP_vec4_GParam.vec4Ptr[CA_IndexA.x];\n";
							属性变量 += "vec4 custom_attr_vec4_b = CAP_vec4_GParam.vec4Ptr[CA_IndexA.y];\n";
							属性变量 += "vec4 custom_attr_vec4_c = CAP_vec4_GParam.vec4Ptr[CA_IndexA.z];\n";

							属性变量 += "custom_attr_vec4" + 属性变量名称 + " = " + f_着色器插值代码构建("custom_attr_vec4_a", "custom_attr_vec4_b", "custom_attr_vec4_c") + ";\n";
							属性变量 += "}\n";

							socket->f_setCode("custom_attr_vec4" + 属性变量名称);
							break;
						}
						case E_值类型::e_Type_iVec2: {
							属性变量 += "ivec2 custom_attr_ivec2" + 属性变量名称 + " = ivec2(0);\n";
							属性变量 += "{\n";
							属性变量 += 变量偏移;
							属性变量 += "ivec2 custom_attr_ivec2_a = CAP_ivec2_GParam.ivec2Ptr[CA_IndexA.x];\n";
							属性变量 += "ivec2 custom_attr_ivec2_b = CAP_ivec2_GParam.ivec2Ptr[CA_IndexA.y];\n";
							属性变量 += "ivec2 custom_attr_ivec2_c = CAP_ivec2_GParam.ivec2Ptr[CA_IndexA.z];\n";

							属性变量 += "custom_attr_ivec2" + 属性变量名称 + " = " + f_着色器插值代码构建("custom_attr_ivec2_a", "custom_attr_ivec2_b", "custom_attr_ivec2_c") + ";\n";
							属性变量 += "}\n";

							socket->f_setCode("custom_attr_ivec4" + 属性变量名称);
							break;
						}
						case E_值类型::e_Type_iVec3: {
							属性变量 += "ivec3 custom_attr_ivec3" + 属性变量名称 + " = ivec3(0);\n";
							属性变量 += "{\n";
							属性变量 += 变量偏移;
							属性变量 += "ivec3 custom_attr_ivec3_a = CAP_ivec3_GParam.ivec3Ptr[CA_IndexA.x];\n";
							属性变量 += "ivec3 custom_attr_ivec3_b = CAP_ivec3_GParam.ivec3Ptr[CA_IndexA.y];\n";
							属性变量 += "ivec3 custom_attr_ivec3_c = CAP_ivec3_GParam.ivec3Ptr[CA_IndexA.z];\n";

							属性变量 += "custom_attr_ivec3" + 属性变量名称 + " = " + f_着色器插值代码构建("custom_attr_ivec3_a", "custom_attr_ivec3_b", "custom_attr_ivec3_c") + ";\n";
							属性变量 += "}\n";

							socket->f_setCode("custom_attr_ivec4" + 属性变量名称);
							break;
						}
						case E_值类型::e_Type_iVec4: {
							属性变量 += "ivec4 custom_attr_ivec4" + 属性变量名称 + " = ivec4(0);\n";
							属性变量 += "{\n";
							属性变量 += 变量偏移;
							属性变量 += "ivec4 custom_attr_ivec4_a = CAP_ivec4_GParam.ivec4Ptr[CA_IndexA.x];\n";
							属性变量 += "ivec4 custom_attr_ivec4_b = CAP_ivec4_GParam.ivec4Ptr[CA_IndexA.y];\n";
							属性变量 += "ivec4 custom_attr_ivec4_c = CAP_ivec4_GParam.ivec4Ptr[CA_IndexA.z];\n";

							属性变量 += "custom_attr_ivec4" + 属性变量名称 + " = " + f_着色器插值代码构建("custom_attr_ivec4_a", "custom_attr_ivec4_b", "custom_attr_ivec4_c") + ";\n";
							属性变量 += "}\n";

							socket->f_setCode("custom_attr_ivec4" + 属性变量名称);
							break;
						}
						default:
							break;
					}
					break;
				}
			}
			
			break;
		}
		case DEF_ShaderAttrLayout_Face: {
			//变量数量 = 面属性变量数量;
			//std::string 面变量偏移 = "uint(customAttrF_GParam.CustomAttrPtr[uint(Resource_ObMesh.m_CustomAttrOffset_F) + " + 属性局部偏移 + " ].offset) + callSceneData.PrimitiveIndex";
			
			switch (着色阶段) {
				case E_着色阶段::e_几何着色:
				case E_着色阶段::e_像素着色: {
					auto 索引 = 属性变量数量 + " > 0 ? " + 属性变量偏移 + " + inPrimitiveID : 0";
					//auto 索引 = 属性变量数量 + " > 0 ? " + "inPrimitiveID : 0";
					//auto 索引 = 属性变量数量 + " > 0 ? " + 属性变量偏移 + " : 0";
					//auto 索引 = 属性变量数量 + " > 0 ? 0 : 0";
					属性变量 += f_面和实例网格自定义着色器数据代码生成(socket, 属性, 属性变量名称, 索引);

					//switch (属性.m_Type) {
					//	case E_值类型::e_Type_I32: {
					//		属性变量 += "custom_attr_i32" + 属性变量名称 + " = CAF_i32_GParam.i32Ptr[" + 索引 + "];\n";
					//		socket->f_setCode("custom_attr_i32" + 属性变量名称);
					//		break;
					//	}
					//	case E_值类型::e_Type_UI32: {
					//		属性变量 += "custom_attr_ui32" + 属性变量名称 + " = CAF_ui32_GParam.ui32Ptr[" + 索引 + "];\n";
					//		socket->f_setCode("custom_attr_ui32" + 属性变量名称);
					//		break;
					//	}
					//	case E_值类型::e_Type_F32: {
					//		属性变量 += "custom_attr_f32" + 属性变量名称 + " = CAF_f32_GParam.f32Ptr[" + 索引 + "];\n";
					//		socket->f_setCode("custom_attr_f32" + 属性变量名称);
					//		break;
					//	}
					//	case E_值类型::e_Type_Vec2: {
					//		属性变量 += "custom_attr_vec2" + 属性变量名称 + " = CAF_vec2_GParam.vec2Ptr[" + 索引 + "];\n";
					//		socket->f_setCode("custom_attr_vec2" + 属性变量名称);
					//		break;
					//	}
					//	case E_值类型::e_Type_Vec3: {
					//		属性变量 += "custom_attr_vec3" + 属性变量名称 + " = CAF_vec3_GParam.vec3Ptr[" + 索引 + "];\n";
					//		socket->f_setCode("custom_attr_vec3" + 属性变量名称);
					//		break;
					//	}
					//	case E_值类型::e_Type_Vec4: {
					//		属性变量 += "custom_attr_vec4" + 属性变量名称 + " = CAF_vec4_GParam.vec4Ptr[" + 索引 + "];\n";
					//		socket->f_setCode("custom_attr_vec4" + 属性变量名称);
					//		break;
					//	}
					//	case E_值类型::e_Type_iVec2: {
					//		属性变量 += "custom_attr_ivec2" + 属性变量名称 + " = CAF_ivec2_GParam.ivec2Ptr[" + 索引 + "];\n";
					//		socket->f_setCode("custom_attr_ivec2" + 属性变量名称);
					//		break;
					//	}
					//	case E_值类型::e_Type_iVec3: {
					//		属性变量 += "custom_attr_ivec3" + 属性变量名称 + " = CAF_ivec3_GParam.ivec3Ptr[" + 索引 + "];\n";
					//		socket->f_setCode("custom_attr_ivec3" + 属性变量名称);
					//		break;
					//	}
					//	case E_值类型::e_Type_iVec4: {
					//		属性变量 += "custom_attr_ivec4" + 属性变量名称 + " = CAF_ivec4_GParam.ivec4Ptr[" + 索引 + "];\n";
					//		socket->f_setCode("custom_attr_ivec4" + 属性变量名称);
					//		break;
					//	}
					//	default:
					//		break;
					//}
					break;
				}
				default:{
					//属性变量偏移 += " + callSceneData.PrimitiveIndex";
					auto 索引 = 属性变量数量 + " > 0 ? " + 属性变量偏移 + " + callSceneData.PrimitiveIndex : 0";

					属性变量 += f_面和实例网格自定义着色器数据代码生成(socket, 属性, 属性变量名称, 索引);

					//switch (属性.m_Type) {
					//	case E_值类型::e_Type_I32: {
					//		属性变量 += "int custom_attr_i32" + 属性变量名称 + " = CAF_i32_GParam.i32Ptr[" + 属性变量数量 + " > 0 ? " + 属性变量偏移 + " : 0];\n";
					//		socket->f_setCode("custom_attr_i32" + 属性变量名称);
					//		break;
					//	}
					//	case E_值类型::e_Type_UI32: {
					//		属性变量 += "uint custom_attr_ui32" + 属性变量名称 + " = CAF_ui32_GParam.ui32Ptr[" + 属性变量数量 + " > 0 ? " + 属性变量偏移 + " : 0];\n";
					//		socket->f_setCode("custom_attr_ui32" + 属性变量名称);
					//		break;
					//	}
					//	case E_值类型::e_Type_F32: {
					//		属性变量 += "float custom_attr_f32" + 属性变量名称 + " = CAF_f32_GParam.f32Ptr[" + 属性变量数量 + " > 0 ? " + 属性变量偏移 + " : 0];\n";
					//		//属性变量 += "debugPrintfEXT(\"Test\");\n";
					//		socket->f_setCode("custom_attr_f32" + 属性变量名称);
					//		break;
					//	}
					//	case E_值类型::e_Type_Vec2: {
					//		属性变量 += "vec2 custom_attr_vec2" + 属性变量名称 + " = CAF_vec2_GParam.vec2Ptr[" + 属性变量数量 + " > 0 ? " + 属性变量偏移 + " : 0];\n";
					//		socket->f_setCode("custom_attr_vec2" + 属性变量名称);
					//		break;
					//	}
					//	case E_值类型::e_Type_Vec3: {
					//		属性变量 += "vec3 custom_attr_vec3" + 属性变量名称 + " = CAF_vec3_GParam.vec3Ptr[" + 属性变量数量 + " > 0 ? " + 属性变量偏移 + " : 0];\n";
					//		socket->f_setCode("custom_attr_vec3" + 属性变量名称);
					//		break;
					//	}
					//	case E_值类型::e_Type_Vec4: {
					//		属性变量 += "vec4 custom_attr_vec4" + 属性变量名称 + " = CAF_vec4_GParam.vec4Ptr[" + 属性变量数量 + " > 0 ? " + 属性变量偏移 + " : 0];\n";
					//		socket->f_setCode("custom_attr_vec4" + 属性变量名称);
					//		break;
					//	}
					//	case E_值类型::e_Type_iVec2: {
					//		属性变量 += "ivec2 custom_attr_ivec2" + 属性变量名称 + " = CAF_ivec2_GParam.ivec2Ptr[" + 属性变量数量 + " > 0 ? " + 属性变量偏移 + " : 0];\n";
					//		socket->f_setCode("custom_attr_ivec2" + 属性变量名称);
					//		break;
					//	}
					//	case E_值类型::e_Type_iVec3: {
					//		属性变量 += "ivec3 custom_attr_ivec3" + 属性变量名称 + " = CAF_ivec3_GParam.ivec3Ptr[" + 属性变量数量 + " > 0 ? " + 属性变量偏移 + " : 0];\n";
					//		socket->f_setCode("custom_attr_ivec3" + 属性变量名称);
					//		break;
					//	}
					//	case E_值类型::e_Type_iVec4: {
					//		属性变量 += "ivec4 custom_attr_ivec4" + 属性变量名称 + " = CAF_ivec4_GParam.ivec4Ptr[" + 属性变量数量 + " > 0 ? " + 属性变量偏移 + " : 0];\n";
					//		socket->f_setCode("custom_attr_ivec4" + 属性变量名称);
					//		break;
					//	}
					//	default:
					//		break;
					//}
					break;
				}
			}
			break;
		}
		case DEF_ShaderAttrLayout_Instance: {
			属性变量偏移 = "uint(customObInstanceAttr_GParam.CustomAttrPtr[Element.MaterialSlot * " + 槽内数量 + " + " + 属性局部偏移 + "].offset)";
			属性变量数量 = "uint(customObInstanceAttr_GParam.CustomAttrPtr[Element.MaterialSlot * " + 槽内数量 + " + " + 属性局部偏移 + "].num)";

			switch (着色阶段) {
				case E_着色阶段::e_几何着色:
				case E_着色阶段::e_像素着色: {
					break;
				}
				default:{
					auto 索引 = 属性变量数量 + " > 0 ? " + 属性变量偏移 + " + rtOb.m_InstanceID : 0";
					//auto 索引 = 属性变量数量 + " > 0 ? " + 属性变量偏移 + " + 0 : 0";
					属性变量 += f_面和实例网格自定义着色器数据代码生成(socket, 属性, 属性变量名称, 索引);
					break;
				}
			}
			break;
		}
	}
	return 属性变量;
}

std::string f_实例自定义着色器数据代码生成(C_插座基类* socket, S_实例自定义属性& 属性, uint32 i, E_着色阶段 着色阶段) {
	std::string 属性变量名称 = f_整数值转字符串(i);

	return "";
}

static std::string f_代码生成_网格自定义属性全局变量节点(C_节点树* tree, E_着色阶段 着色阶段) {
	std::string 网格自定义属性;
	uint32 网格属性插座数量 = tree->m_网格属性变量->f_get输出插座数量();
	for (uint32 i = 1; i < 网格属性插座数量; ++i) {
		auto* socket = tree->m_网格属性变量->f_get输出插座(i);
		S_网格自定义属性& 属性 = DEF_网格自定义属性插座数据(socket);
		网格自定义属性 += f_网格自定义着色器数据代码生成(socket, 属性, i, 着色阶段);
	}
	return 网格自定义属性;
}

static std::string f_几何着色器代码生成_轮廓边(const std::string& 边宽度实现) {
	std::string shader_code;

	shader_code += "#include \"shader_taster_edge.h\" \n";


	shader_code += "void f_edge_width(int index, in float width, in vec4 color, in vec3 normal, in vec4 vert){\n";
	shader_code += 边宽度实现;
	shader_code += "}\n";

	return shader_code;
}

static std::string f_几何着色器代码生成(C_节点树* 子集节点树) {
	std::string shader_code;

	shader_code = f_片源着色器引入();

	std::string 实现代码;
	std::string 函数变量声明;
	std::vector<std::string> 函数定义;

	if (子集节点树) {
		子集节点树->m_目标代码 = E_编译目标代码::e_编译目标代码_Geom;
		实现代码 = f_NT_编译节点树(子集节点树, 函数定义, 函数变量声明);
		shader_code += 函数变量声明;
		for (auto& e : 函数定义) {
			shader_code += e;
		}
	}
	


	shader_code += "layout(location = 0) in vec4 vColor;\n";
	shader_code += "layout(location = 1) in vec3 vNormal;\n";
	shader_code += "layout(location = 2) in vec3 vCamera[4];\n";
	//shader_code += "layout(location = 6) in float DepthScale;\n";

	shader_code += "layout(location=0) out vec4 outColor;\n";
	shader_code += "void main() {\n";
	shader_code += "S_SceneDataCall callSceneData;\n";

	//shader_code += f_片源着色器引用变量定义();
	//shader_code += f_像素着色器网格属性定义();
	//shader_code += 网格自定义属性;
	//shader_code += 光栅属性变量;
	shader_code += 实现代码;
	//shader_code += f_光追回调着色器输出参数代码构建(outNodes, m_Code);

	shader_code += "outColor = vec4(callSceneData.Color, 1);\n";

	shader_code += "}\n";
}

//std::string f_着色器自定义数据代码生成(C_插座基类* socket, S_网格自定义属性& 属性, uint32 i) {
//	std::string 属性变量;
//	std::string 属性局部偏移 = f_整数值转字符串(属性.m_OffsetID);
//	std::string 属性变量名称 = f_整数值转字符串(i);
//	
//	std::string 属性变量偏移 = "uint(customAttr_GParam.CustomAttrPtr[Element.MaterialSlot * 32 + " + 属性局部偏移 + "].offset)";
//	std::string 属性变量数量 = "uint(customAttr_GParam.CustomAttrPtr[Element.MaterialSlot * 32 + " + 属性局部偏移 + "].num)";
//
//	return "";
//}



C_材质槽节点::C_材质槽节点(S_设备环境& ctx) : C_节点基类(DEF_材质槽节点, E_节点类型::e_节点Type_材质) {
	f_setWName(u"材质");
	m_Ctx = ctx;
	
	C_插座基类* socket;
	DEF_创建UI32插座_I(u"数量");
	DEF_创建材质_1D插座_O(u"材质", ctx);

	DEF_UI32插座数据(f_get输入插座(1)) = 1;

	materials = (S_MaterialArray*)f_core_array_new(1, sizeof(S_材质管线*));
	materials->ptr_userData[0] = f_material_createPBR();
}

C_材质槽节点::~C_材质槽节点() {
	//auto* materials = DEF_材质插座_1D数据(f_get输出插座(1), 0);

	uint32 数量 = materials->count;
	for (uint32 i = 0; i < 数量; ++i) {
		S_材质管线* mat = f_array_at(S_材质管线*, materials, i);
		f_material_releasePBR(mat);
	}
	f_core_array_free((S_Array*)materials);
}

bool C_材质槽节点::f_update() {
	uint32 num = DEF_UI32插座数据(f_get输入插座(1));
	//auto* materials = DEF_材质插座_1D数据(f_get输出插座(1), 0);

	uint32 原数量 = materials->count;

	if (原数量 > num) {
		for (uint32 i = num; i < 原数量; ++i) {
			//S_材质* mat = f_array_at(S_材质*, materials, i);
			S_材质管线* mat = *(S_材质管线**)f_core_array_back((S_Array*)materials);
			f_material_releasePBR(mat);
			f_core_array_pop_back((S_Array*)materials);
		}
	}
	else {
		for (uint32 i = 原数量; i < num; ++i) {
			S_材质管线* mat = f_material_createPBR();
			f_core_array_push_back((S_Array*)materials, (uint8*)&mat);
		}
	}

	f_get输出插座(1)->f_setData(materials);
	return false;
}

C_节点基类* f_node_创建材质槽节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_材质槽节点(ctx);
}

C_节点基类* f_node_加载材质槽节点(S_设备环境& ctx, FILE* f) {
	C_材质槽节点* node = new C_材质槽节点(ctx);
	return node;
}

void f_node_保存材质槽节点(C_节点基类* n, FILE* f) {
	C_材质槽节点* node = dynamic_cast<C_材质槽节点*>(n);
}




C_材质编辑节点::C_材质编辑节点(S_设备环境& ctx, C_节点树* link_tree) : C_节点基类(DEF_材质编辑节点, E_节点类型::e_节点Type_材质) {
	f_setWName(u"材质编辑");
	m_Ctx = ctx;
	m_材质 = f_material_createPBR();

	C_插座基类* socket;
	DEF_创建材质_1D插座_I(u"材质");
	DEF_创建材质_1D插座_O(u"材质", ctx);

	m_材质节点树 = f_alloc_StrIndexProp(S_节点数据::g_材质节点树, u"");
	m_材质节点树.m_私有 = true;

	m_灯光标志位 = f_alloc_UI32FlagBitsProp(nullptr, u"灯光遮罩");
	m_灯光标志位.m_私有 = true;
	f_prop_UI32(m_灯光标志位) = 1;

	//m_构建材质类型 = f_alloc_EnumProp(nullptr, {
	//	{L"光追"},
	//	{L"光栅"},
	//}, L"着色器类型");
	//m_构建材质类型.m_私有 = true;

	m_构建材质片源类型 = f_alloc_FlagBitsEnumProp(nullptr, *S_节点数据::g_片源着色器类型项, u"着色器类型", 3);
	m_构建材质片源类型.m_私有 = true;

	m_构建材质几何类型 = f_alloc_EnumProp(nullptr, {{u"面", u""}, {u"边", u""}, {u"线", u""}}, u"几何类型");
	m_构建材质几何类型.m_私有 = true;


	if (!link_tree) {
		link_tree = f_node_Create材质节点树(false, u"material_");

		auto* inNode = new C_输入组节点(ctx, 2);
		auto* outNode = new C_输出组节点(ctx);

		f_su_拷贝插座(this, outNode, E_插座方向::e_插座Type_输出, E_插座方向::e_插座Type_输入);

		socket = new C_着色器插座(u"片源");
		outNode->f_add插座(socket, E_插座方向::e_插座Type_输入);

		socket = new C_着色器插座(u"几何");
		outNode->f_add插座(socket, E_插座方向::e_插座Type_输入);

		socket = new C_着色器插座(u"线几何");
		outNode->f_add插座(socket, E_插座方向::e_插座Type_输入);

		socket = new C_着色器插座(u"顶点");
		outNode->f_add插座(socket, E_插座方向::e_插座Type_输入);


		inNode->f_add插座(new C_材质_1D插座(u"材质"), E_插座方向::e_插座Type_输出);
		//f_su_拷贝插座(this, inNode, E_插座方向::e_插座Type_输入, E_插座方向::e_插座Type_输出);
		inNode->m_插座可编辑 = true;
		//link_tree->f_添加节点(inNode);
		//link_tree->f_添加节点(outNode);
		f_node_节点树添加节点(link_tree, inNode);
		f_node_节点树添加节点(link_tree, outNode);

		auto 全局变量 = new C_全局变量节点(ctx);
		全局变量->f_setWName(u"全局变量");
		f_node_节点树添加节点(link_tree, 全局变量);

		auto 网格属性 = new C_网格属性变量节点(ctx);
		网格属性->f_setWName(u"网格属性");
		f_node_节点树添加节点(link_tree, 网格属性);

		inNode->m_坐标 = { 000, 400 };
		outNode->m_坐标 = { 800, 400 };
	}
	f_prop_MatPtr_切换ID(m_材质节点树, link_tree);


	C_节点基类::f_绑定子集节点树(link_tree);
	f_绑定this节点树(link_tree);
	link_tree->f_set父节点(this);

	f_get子集输入节点(m_InNodes);
	for (auto& e : m_InNodes) {
		e->f_set可添加删除插座起始位置(1,1);
	}

	m_函数指针 = nullptr;
}

C_材质编辑节点::~C_材质编辑节点() {
	f_material_releasePBR(m_材质);
	f_prop_Release(m_灯光标志位);
	f_prop_Release(m_构建材质片源类型);
	f_prop_Release(m_构建材质几何类型);
}

void C_材质编辑节点::f_get子集输入节点(std::vector<C_节点基类*>& inNodes) {
	inNodes.clear();
	for (auto& e : m_子集节点树->m_Nodes) {
		if (e->m_Type == E_节点类型::e_节点Type_组输入) {
			inNodes.push_back(e);
		}
	}
}

void C_材质编辑节点::f_get子集输出节点(std::vector<C_节点基类*>& outNodes) {
	outNodes.clear();
	for (auto& e : m_子集节点树->m_Nodes) {
		if (e->m_Type == E_节点类型::e_节点Type_组输出) {
			//outNodes.emplace_back(e);
			outNodes.push_back(e);
		}
	}
}

bool C_材质编辑节点::f_update() {
	S_MaterialArray* materials;
	
	if (f_get输入插座(1)->f_isLink()) {
		materials = DEF_材质插座_1D数据(f_get输入插座(1), 0);
		f_get输出插座(1)->f_setData(materials);
	}
	else {
		f_get输出插座(1)->f_setData((void*)nullptr);
		materials = DEF_材质插座_1D数据(f_get输出插座(1), 0);

		f_core_array_resize((S_Array*)materials, 1);
		materials->ptr_userData[0] = m_材质;
	}


	if (!m_子集节点树->m_程序集 || m_子集节点树->m_节点结构改变) {
		
		if (!m_子集节点树->m_开始编译) {
			m_函数指针 = nullptr;
			m_子集节点树->f_准备编译节点树();

			m_子集节点树->m_开始编译 = true;
			f_NodeCtx_节点模拟入栈(this);
		}
		return true;
	}
	else if (m_子集节点树->m_程序集 && m_子集节点树->m_函数指针) {
		m_函数指针 = (expand_接口函数_材质节点)m_子集节点树->m_函数指针;
	}
	//else if (m_子集节点树->m_程序集 && !m_函数指针) {
	//	std::string 函数名称 = f_WStringToString(m_子集节点树->m_IDName);
	//	E_JIT方式 方式 = (E_JIT方式)f_prop_enum(m_子集节点树->m_编译方式);
	//	m_函数指针 = (expand_接口函数_材质节点)f_JIT_取函数指针(m_子集节点树->m_程序集, 函数名称, 方式);
	//}


	if (m_函数指针) {
		std::vector<void*> inData;
		uint32 inNum = f_get输入插座数量();
		uint32 outNum = f_get输出插座数量();

		for (uint32 i = 0; i < inNum; ++i) {
			inData.push_back(f_get输入插座(i)->f_getData(0));
		}
		for (uint32 i = 0; i < outNum; ++i) {
			inData.push_back(f_get输出插座(i)->f_getData(0));
		}

		f_get子集输出节点(m_OutNudes);


		S_Scene* scene = f_NodeCtx_get默认场景();
		S_着色* shader = DEF_着色器数据(m_OutNudes[0]->f_get输入插座(2), 0);

		for (uint32 i = 0; i < materials->count; ++i) {
			f_JIT_清除材质自定义网格数据布局参数(*materials->ptr_userData[i]);
			
			uint32 插座数量 = m_子集节点树->m_网格属性变量->f_get输出插座数量();
			for (uint32 attrID = 1; attrID < 插座数量; ++attrID) {
				auto* socket = m_子集节点树->m_网格属性变量->f_get输出插座(attrID);

				S_网格自定义属性& 属性 = DEF_网格自定义属性插座数据(socket);
				属性.m_OffsetID = attrID - 1;
				属性.m_Name = &socket->m_identifier;

				materials->ptr_userData[i]->m_网格自定义属性布局.push_back(属性);
			}


			uint32 全局光照材质Offset = materials->ptr_userData[i]->m_材质属性ID;
			
			auto& GPU材质 = f_buf_Material_at(materials->ptr_userData[i]->m_材质属性, 0);
			
			GPU材质.m_LigthMask = f_prop_UI32(m_灯光标志位);
			GPU材质.m_colorTex = -1;
			GPU材质.m_emissionTex = -1;
			GPU材质.m_reflectTex = -1;
			GPU材质.m_refractTex = -1;
			GPU材质.m_roughnessTex = -1;
			GPU材质.m_alphaTex = -1;
			
			
			bool r = m_函数指针(GPU材质, i, *materials->ptr_userData[i], inData.data(), C_节点树::g_节点JIT参数.data());
			//bool r = m_函数指针(GPU材质[全局光照材质Offset], inData.data(), nullptr);
			GPU材质.m_CustomAttrOffset = f_buf_getOffsetAddress(materials->ptr_userData[i]->m_材质自定义属性索引);
			GPU材质.m_shaderIndex = shader->m_ShaderIndex;
		}
	}
	else {
		//materials->ptr_userData[0]->m_Shader = nullptr;
	}
	
	return false;
}

void C_材质编辑节点::f_异步解算() {
	if(!m_子集节点树) return;

	std::string 材质函数名称 = f_str_u16_to_u8(m_子集节点树->m_IDName);
	E_JIT方式 方式 = (E_JIT方式)f_prop_enum(m_子集节点树->m_编译方式);

	m_函数指针 = nullptr;
	m_编译成功 = true;



	//------------------------ 临时旧版本兼容 -----------------------------------
	if (!m_子集节点树->m_全局变量 || !m_子集节点树->m_网格属性变量) {
		auto 全局变量 = new C_全局变量节点(m_Ctx);
		全局变量->f_setWName(u"全局变量");
		f_node_节点树添加节点(m_子集节点树, 全局变量);

		auto 网格属性 = new C_网格属性变量节点(m_Ctx);
		网格属性->f_setWName(u"网格属性");
		f_node_节点树添加节点(m_子集节点树, 网格属性);
	}
	
	for (auto& node : m_子集节点树->m_Nodes) {
		auto* st = node->f_get子集树();
		if (st) {
			f_node_绑定子节点树全局变量(st, m_子集节点树->m_全局变量, m_子集节点树->m_网格属性变量);
		}
	}
	
	
	

	std::string path = f_file_get路径(S_节点数据::g_工程文件材质节点代码绝对路径) + 材质函数名称 + ".cpp";
	bool 编译成功 = f_NT_编译节点(this, path, true);


	switch (方式) {
		case E_JIT方式::e_jit_llvm: path = f_file_get路径(S_节点数据::g_工程文件材质节点代码绝对路径) + 材质函数名称 + ".bc"; break;
		case E_JIT方式::e_jit_dll: path = f_file_get路径(S_节点数据::g_工程文件材质节点代码绝对路径) + 材质函数名称 + ".ex"; break;
	}


	
	if (编译成功 && f_file_文件是否存在(path)) {
		if (m_子集节点树->f_加载程序集(path, 方式)) {
			return;
		}
		goto To_重新编译;
	}
	else {
	To_重新编译:
		//f_node_销毁程序集(m_子集节点树);
		m_编译成功 = false;
		//m_函数指针 = (expand_接口函数_材质节点)f_JIT_取函数指针(m_子集节点树->m_程序集, 材质函数名称, 方式);
	}

	f_set是否要更新(true);
}

void C_材质编辑节点::f_重新绑定程序集(uint64 函数指针) {
	//(expand_接口函数_函数节点)f_NT_初始化函数接口(m_子集节点树->m_程序集, 函数名称, 方式);
	m_函数指针 = (expand_接口函数_材质节点)函数指针;
}

void C_材质编辑节点::f_清除程序集() {
	m_函数指针 = nullptr;
}

std::string C_材质编辑节点::DEF_节点编译函数{
	m_Code = "";
	m_ReleaseCode = "";

	//std::string name = f_WStringToString(f_prop_Str(m_子集节点树->m_函数名称));
	std::string name = f_str_u16_to_u8(m_子集节点树->m_IDName);
	uint32 inNum = f_get输入插座数量();
	uint32 outNum = f_get输出插座数量();



	bool 内联调用 = f_NT_是否内联调用(this);
	bool 编译 = true;
	if (内联调用) {
		name += "_inline";

		if (m_子集节点树->m_以编译 & E_节点树编译位标志::e_节点编译_内联调用) {
			编译 = false;
		}
	}
	else {
		if (m_子集节点树->m_以编译 & E_节点树编译位标志::e_节点编译_外部调用) {
			编译 = false;
		}
	}



	if (编译) {
		if (内联调用) {
			m_子集节点树->m_以编译 |= E_节点树编译位标志::e_节点编译_内联调用;
		}
		else {
			m_子集节点树->m_以编译 |= E_节点树编译位标志::e_节点编译_外部调用;
		}

		m_子集节点树->m_以编译 = E_节点树编译位标志::e_节点编译_完成;

		//std::string 函数声明 = "// ======== " + name + " ========\n";
		std::string 函数声明 = " bool " + name + "(" + DEF_S(S_Material) + "& self, int32 " + f_代码构建_ID变量名称(this) + ", S_材质管线& 材质, void** inData, " + DEF_S(DEF_编译可调参数) + ")";

		声明 += "static " DEF_S(DEF_编译全局可调参数) " = nullptr;\n";
		声明 += "// ======== " + name + " ========\n";

		std::string extern_declspec = "extern \"C\" { __declspec(dllexport) ";
		if (extern_declspec.size()) {
			声明 += extern_declspec + 函数声明 + ";}\n";
		}
		else {
			声明 += 函数声明 + ";\n";
		}




		std::string 函数定义 = 函数声明;
		函数定义 += "{\n";

		f_get子集输入节点(m_InNodes);
		f_get子集输出节点(m_OutNudes);
		f_代码构建_输入输出节点参数(this, m_InNodes, {});


		



		函数定义 += DEF_S(DEF_编译全局可调参数赋值)";\n";
		函数定义 += "S_Material* " + g材质_参数 + " = &self;\n";

		函数定义 += f_NT_编译节点树(m_子集节点树, 定义, 声明);

		函数定义 += DEF_S(f_JIT_绑定材质着色器)"(材质, *(const S_材质*)(" + DEF_指针转字符串(m_材质) + ") );\n";

		函数定义 += "return true;\n";
		函数定义 += "}\n";
		定义.push_back(函数定义);


		//线管创建
		S_着色器创建配置 图元配置;
		图元配置.m_Paths.push_back({ S_引擎配置::m_3D着色器文件根路径 + "物理光照_顶点阶段.spv", {}, E_着色阶段::e_顶点着色 });
		//图元配置.m_Paths.push_back({ S_引擎配置::m_3D着色器文件根路径 + "物理光照_片源阶段.spv", {}, E_着色阶段::e_像素着色 });

		图元配置.m_参数布局 = {
								{ 0, E_着色阶段::e_顶点着色, E_板载缓存类型::e_UBO},
								{ 1, E_着色阶段::e_顶点着色, E_板载缓存类型::e_SSBO },
								//{ 2, E_着色阶段::e_顶点着色, E_板载缓存类型::e_UBO },		//灯光方向
								{ DEF_BINDING_WIDGET_Color, E_着色阶段::e_顶点着色, E_板载缓存类型::e_SSBO },
								{ DEF_BINDING_Bones_Props, E_着色阶段::e_顶点着色, E_板载缓存类型::e_SSBO },
								{ DEF_BINDING_Bones_Map, E_着色阶段::e_顶点着色, E_板载缓存类型::e_SSBO },
								{ DEF_BINDING_Bones_Matrix, E_着色阶段::e_顶点着色, E_板载缓存类型::e_SSBO },
								{ DEF_BINDING_LineProp, E_着色阶段::e_顶点着色, E_板载缓存类型::e_SSBO },

								//{ DEF_TasterTexturesBindID_rgba32f, E_着色阶段::e_计算着色, E_板载缓存类型::e_SAMPLER_Array},
								
								{ DEF_BINDING_ObMesh, E_着色阶段::e_几何着色, E_板载缓存类型::e_SSBO },
								{ DEF_BINDING_TasterBindID_Face, E_着色阶段::e_几何着色, E_板载缓存类型::e_SSBO },
								{ DEF_BINDING_TasterBindID_TexCoord, E_着色阶段::e_几何着色, E_板载缓存类型::e_SSBO },
								{ DEF_BINDING_TasterBindID_TexIndex, E_着色阶段::e_几何着色, E_板载缓存类型::e_SSBO },

								{ DEF_BINDING_Render_GlobalParam, E_着色阶段::e_几何着色 | E_着色阶段::e_像素着色, E_板载缓存类型::e_SSBO },
								{ DEF_BINDING_Face_AttrIndex, E_着色阶段::e_顶点着色 | E_着色阶段::e_几何着色 | E_着色阶段::e_像素着色, E_板载缓存类型::e_SSBO },
								{ DEF_BINDING_Material_AttrIndex, E_着色阶段::e_顶点着色 | E_着色阶段::e_几何着色 | E_着色阶段::e_像素着色, E_板载缓存类型::e_SSBO },

								{ DEF_MaterialsBindID, E_着色阶段::e_像素着色, E_板载缓存类型::e_SSBO },
								{ DEF_TasterTexturesBindID_rgba8, E_着色阶段::e_像素着色, E_板载缓存类型::e_SAMPLER_Array},

								{ DEF_TasterTexturesBindID_rgba32ui, E_着色阶段::e_像素着色, E_板载缓存类型::e_SSBO},
								{ DEF_TasterTexturesBindID_r32ui, E_着色阶段::e_像素着色, E_板载缓存类型::e_IMAGE},
								{ DEF_TasterBindID_AlphaListCount, E_着色阶段::e_像素着色, E_板载缓存类型::e_SSBO},
		};

		E_几何着色类型 几何着色类型 = E_几何着色类型::e_几何着色_面;
		S_线管创建参数 线管参数({ 1024, 1024 });
		线管参数.m_绘制方式 = E_绘制方式::e_三角形;
		线管参数.m_填充模式 = E_填充模式::e_填充面;
		线管参数.m_采样 = m_Ctx.m_采样数;


		auto* 片源着色Socket = m_OutNudes[0]->f_get输入插座(2);
		auto* 几何着色Socket = m_OutNudes[0]->f_get输入插座(3);

		


		if (片源着色Socket) {
			auto* 片源着色OutSocket = 片源着色Socket->f_getLinkOutSocket(0);

			S_着色* shader = DEF_着色器数据(片源着色Socket);

			if (片源着色OutSocket) {
				auto 片源着色器节点 = 片源着色OutSocket->f_getNode();
				C_PBR材着色器节点* shader = dynamic_cast<C_PBR材着色器节点*>(片源着色器节点);

				auto 后缀 = f_file_get文件名后缀(shader->m_SPV);
				if (后缀 == ".fspv") {
					图元配置.m_Paths.push_back({ shader->m_SPV, {}, E_着色阶段::e_像素着色 });
				}
				else goto To_默认像素着色器;
			}
			else {
			To_默认像素着色器:
				图元配置.m_Paths.push_back({ S_引擎配置::m_3D着色器文件根路径 + "物理光照_片源阶段.spv", {}, E_着色阶段::e_像素着色 });
			}
		}
		

		std::string 几何着色器文件;
		if (几何着色Socket) {
			auto* 几何着色OutSocket = 几何着色Socket->f_getLinkOutSocket(0);
			if (几何着色OutSocket) {
				auto 几何着色器节点 = 几何着色OutSocket->f_getNode();
				C_PBR材着色器节点* shader = dynamic_cast<C_PBR材着色器节点*>(几何着色器节点);

				auto 后缀 = f_file_get文件名后缀(shader->m_SPV);
				if (后缀 == ".gspv") {
					几何着色器文件 = shader->m_SPV;
					//f_prop_enum(m_构建材质几何类型) = f_prop_enum(shader->m_构建材质几何类型);
				}
				else {
					//goto To_默认几何着色器;
				}
			}
			else {
				//goto To_默认几何着色器;
			}
		}
		else {
		//To_默认几何着色器:
		}
		
		switch (f_prop_enum(m_构建材质几何类型)) {
			case 0: {
				if (几何着色器文件.empty()) 几何着色器文件 = S_引擎配置::m_3D着色器文件根路径 + "物理光照.gspv";
				图元配置.m_Paths.push_back({ 几何着色器文件, {}, E_着色阶段::e_几何着色 });
				m_材质->mf_GPU参数配置 = (fp_set材质GPU参数配置)f_update着色器参数配置;
				break;
			}
			case 1: {
				图元配置.m_参数布局.push_back({ DEF_BINDING_Face_AdjacencyID_BindID, E_着色阶段::e_几何着色, E_板载缓存类型::e_SSBO });
				图元配置.m_参数布局.push_back({ DEF_BINDING_Face_Normal_BindID, E_着色阶段::e_几何着色, E_板载缓存类型::e_SSBO });
				图元配置.m_参数布局.push_back({ DEF_BINDING_Face_Center_BindID, E_着色阶段::e_几何着色, E_板载缓存类型::e_SSBO });
				
				if (几何着色器文件.empty()) 几何着色器文件 = S_引擎配置::m_3D着色器文件根路径 + "物理光照轮廓.gspv";
				图元配置.m_Paths.push_back({ 几何着色器文件, {}, E_着色阶段::e_几何着色 });

				m_材质->mf_GPU参数配置 = (fp_set材质GPU参数配置)f_update轮廓着色器参数配置;
				
				break;
			}
			case 2: {
				if (几何着色器文件.empty()) 几何着色器文件 = S_引擎配置::m_3D着色器文件根路径 + "物理光照线.gspv";
				图元配置.m_Paths.push_back({ 几何着色器文件, {}, E_着色阶段::e_几何着色 });

				线管参数.m_绘制方式 = E_绘制方式::e_画邻接连续线段;
				线管参数.m_填充模式 = E_填充模式::e_填充面;
				break;
			}
		}
		//几何着色类型 = E_几何着色类型(f_prop_enum(shader->m_构建材质几何类型));
		
		图元配置.m_顶点配置 = {
			{0,sizeof(vec3),0,E_数据格式::e_F_RGB},
			{0,sizeof(vec3),0,E_数据格式::e_F_RGB},
			{0,sizeof(vec2),0,E_数据格式::e_F_R32G32},
		};
		图元配置.m_常量偏移和字节数 = { { E_着色阶段::e_顶点着色, 0, sizeof(S_Vert_MeshDrawProp) } };


		f_df_销毁材质着色器(m_材质);
		f_df_创建材质着色器(m_Ctx, m_材质, 图元配置, 线管参数);
		m_材质->m_着色线管->m_几何类型 = E_几何着色类型(f_prop_enum(m_构建材质几何类型));
	}

	



	if (内联调用) {
		m_Code += "{\n";
		for (uint32 i = 0; i < inNum; ++i) {
			m_Code += f_get输入插座(i)->f_构建变量代码(0);
		}
		for (uint32 i = 0; i < outNum; ++i) {
			m_Code += f_get输出插座(i)->f_构建变量代码(0);
		}

		//函数调用代码
		m_Code += name + "(";
		for (uint32 i = 1; i < inNum; ++i) {
			m_Code += f_get输入插座(i)->f_getCode(0);
			if (i < outNum - 2) {
				m_Code += ", ";
			}
		}
		for (uint32 i = 1; i < outNum; ++i) {
			m_Code += ", " + f_get输出插座(i)->f_getCode(0);
		}
		m_Code += ");\n";
		m_Code += "}\n";
	}


	if (m_区域父节点) {
		m_区域父节点->m_Code += m_Code;
		m_区域父节点->m_ReleaseCode += m_ReleaseCode;
		return "";
	}
	释放 += m_ReleaseCode;
	return m_Code;
}

void C_材质编辑节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);

	if (S_引擎配置::g_当前加载文件版本号 <= S_引擎配置::g_低版本号_6) {
		f_prop_Load(m_灯光标志位, f);
	}
	else {
		S_文件块 文件块 = f_file_读取文件块(f);
		if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
			const uint8* 下一次读取数据指针 = 文件块.m_data;

			if (f_file_版本对比(文件块, S_引擎配置::g_低版本号_17, S_引擎配置::g_文件版本号)) {
				下一次读取数据指针 = f_prop_Load(m_构建材质片源类型, 下一次读取数据指针);
				下一次读取数据指针 = f_prop_Load(m_构建材质几何类型, 下一次读取数据指针);
			}
			if (f_file_版本对比(文件块, S_引擎配置::g_低版本号_6, S_引擎配置::g_文件版本号)) {
				下一次读取数据指针 = f_prop_Load(m_灯光标志位, 下一次读取数据指针);
			}
		}
		free(文件块.m_data);
	}
}

void C_材质编辑节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);

	auto 文件块 = f_文件块_创建(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_引擎配置::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	f_prop_Save(m_构建材质片源类型, 块);
	f_prop_Save(m_构建材质几何类型, 块);
	f_prop_Save(m_灯光标志位, 块);

	f_file_保存文件块(f, 文件块, 块);
}

C_节点基类* f_node_创建材质节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_材质编辑节点(ctx, 子节点树);
}

C_节点基类* f_node_加载材质节点(S_设备环境& ctx, FILE* f) {
	std::u16string 链接的节点树名称 = f_file_读取字符串(f);

	if (S_节点数据::G用于重新映射节点树到节点的容器.find(链接的节点树名称) == S_节点数据::G用于重新映射节点树到节点的容器.end()) {
		f_node_加载节点树(ctx, f);
	}

	auto tree = S_节点数据::G用于重新映射节点树到节点的容器[链接的节点树名称];
	C_材质编辑节点* node = new C_材质编辑节点(ctx, tree);

	//if (nullptr == tree->m_全局变量) {
	//	auto 全局变量 = new C_全局变量节点(node->m_Ctx);
	//	全局变量->f_setWName(L"全局变量");
	//	f_node_节点树添加节点(tree, 全局变量);
	//}
	//if (nullptr == tree->m_网格属性变量) {
	//	auto 网格属性 = new C_网格属性变量节点(node->m_Ctx);
	//	网格属性->f_setWName(L"网格属性");
	//	f_node_节点树添加节点(tree, 网格属性);
	//}

	return node;
}

void f_node_保存材质节点(C_节点基类* n, FILE* f) {
	C_材质编辑节点* node = dynamic_cast<C_材质编辑节点*>(n);

	auto* tree = node->f_get子集树();
	f_file_保存字符串(f, tree->m_IDName);

	if (tree->m_未保存或加载) {
		tree->m_未保存或加载 = false;

		std::vector<C_节点树*> trees = { tree };
		f_node_保存节点树(trees, f);
	}
}




C_当前材质节点::C_当前材质节点(S_设备环境& ctx) : C_节点基类(DEF_当前材质节点, E_节点类型::e_节点Type_材质) {
	f_setWName(u"当前材质");
	m_Ctx = ctx;

	C_插座基类* socket;
	//DEF_创建材质插座_I(L"材质");
	DEF_创建材质插座_O(u"材质", ctx);

}

C_当前材质节点::~C_当前材质节点() {
}

bool C_当前材质节点::f_update() {
	return false;
}

std::string C_当前材质节点::DEF_节点编译函数{
	m_Code = "";
	m_ReleaseCode = "";

	auto name = "(&self)";

	f_get输出插座(1)->f_setCode(name);
	if (m_区域父节点) {
		m_区域父节点->m_Code += m_Code;
		return "";
	}
	return m_Code;
}

void C_当前材质节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	S_文件块 文件块 = f_file_读取文件块(f);
	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;
		//if (f_file_版本对比(文件块, S_节点数据::g_低版本号_6, S_节点数据::g_文件版本号)) {
		//}
	}
	free(文件块.m_data);
}

void C_当前材质节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	auto 文件块 = f_文件块_创建(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_引擎配置::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	f_file_保存文件块(f, 文件块, 块);
}

C_节点基类* f_node_创建当前材质节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_当前材质节点(ctx);
}

C_节点基类* f_node_加载当前材质节点(S_设备环境& ctx, FILE* f) {
	C_当前材质节点* node = new C_当前材质节点(ctx);
	return node;
}

void f_node_保存当前材质节点(C_节点基类* n, FILE* f) {
	C_当前材质节点* node = dynamic_cast<C_当前材质节点*>(n);
}





C_自发光材质节点::C_自发光材质节点(S_设备环境& ctx) : C_节点基类(DEF_自发光材质节点, E_节点类型::e_节点Type_材质) {
	f_setWName(u"自发光材质");
	m_Ctx = ctx;

	C_插座基类* socket;


}

C_自发光材质节点::~C_自发光材质节点() {
}

bool C_自发光材质节点::f_update() {
	return false;
}

void C_自发光材质节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
}

void C_自发光材质节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
}

C_节点基类* f_node_加载自发光材质节点(S_设备环境& ctx, FILE* f) {
	C_自发光材质节点* node = new C_自发光材质节点(ctx);
	return node;
}

void f_node_保存自发光材质节点(C_节点基类* n, FILE* f) {
	C_自发光材质节点* node = dynamic_cast<C_自发光材质节点*>(n);
}








C_设置物体材质节点::C_设置物体材质节点(S_设备环境& ctx) : C_节点基类(DEF_设置网格材质节点, E_节点类型::e_节点Type_材质) {
	f_setWName(u"设置物体材质");
	m_Ctx = ctx;

	C_插座基类* socket;
	DEF_创建材质_1D插座_I(u"材质", ctx);
	DEF_创建UI32插座_I(u"槽", ctx);
	DEF_创建物体_1D插座_I(u"物体", ctx);
	
	f_get输入插座(3)->f_set多输入();

	DEF_创建材质_1D插座_O(u"材质", ctx);


	m_材质槽类型 = f_alloc_EnumProp(nullptr, {{u"网格"}, {u"实例遮罩"}, {u"实例ID"}, {u"实例随机筛选"} }, u"材质槽类型");
	m_材质槽类型.m_私有 = true;

	m_清除材质 = f_alloc_BoolProp(nullptr, u"清除材质");
	m_清除材质.m_私有 = true;
	f_prop_Bool(m_清除材质) = false;

	m_随机种子 = f_alloc_I32Prop(nullptr, u"随机种子");
	m_随机种子.m_私有 = true;
	f_prop_I32(m_随机种子) = 0;
}

C_设置物体材质节点::~C_设置物体材质节点() {
	f_prop_Release(m_材质槽类型);
	f_prop_Release(m_清除材质);
	f_prop_Release(m_随机种子);
}

bool C_设置物体材质节点::f_update() {
	
	switch (f_prop_enum(m_材质槽类型)) {
		case 0: {
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 1, E_值类型::e_Type_材质1D);
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 2, E_值类型::e_Type_UI32);
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 3, E_值类型::e_Type_Object_1D);
			
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_材质1D);

			f_get输入插座(2)->f_set单输入();
			f_get输入插座(3)->f_set多输入();

			auto* socket2 = f_get输入插座(2);
			auto* socket3 = f_get输入插座(3);
			socket3->f_set多输入();


			auto* 材质组 = DEF_材质插座_1D数据(f_get输入插座(1), 0);
			auto* mat_ptr = 材质组->ptr_userData;
			uint32 材质数量 = 材质组->count;

			uint32 物体组数量 = socket3->f_getLinkNum();
			uint32 所有输入物体数量 = 0;
			
				
			for (uint32 j = 0; j < 物体组数量; ++j) {
				auto& 物体组 = *DEF_物体插座_1D数据(socket3, j);
				uint32 物体数量 = 物体组.count;

				所有输入物体数量 += 物体数量;
				
				for (uint32 i = 0; i < 物体数量; ++i) {
					S_Mesh* me = f_ob_getMesh(物体组.ptr_userData[i], E_物体网格元素类型::e_MT_光照);
					if (!me) continue;

					uint32 面数量 = me->m_面->m_Mem.m_数量;
					if (!面数量) continue;
				}
			}

			
			if (!材质数量) {
				f_get输出插座(1)->f_setData(材质组);
			}
			else {
				f_get输出插座(1)->f_setData((S_MaterialArray*)nullptr);
			}

			
			bool 材质多例 = 材质数量 >= 所有输入物体数量;


			uint32 槽 = DEF_UI32插座数据(socket2);
			槽 = DEF_Min(槽, DEF_网格自定义属性槽数量 - 1);

			uint32 材质计数 = 0;
			for (uint32 j = 0; j < 物体组数量; ++j) {
				auto& 物体组 = *(S_OBArray*)(socket3->f_getData(j));
				uint32 物体数量 = 物体组.count;



				for (uint32 i = 0; i < 物体数量; ++i) {
					auto* ob = 物体组.ptr_userData[i];
					
					if (材质数量) {
						uint32 光追材质ID;
						S_材质管线* 材质;
						if (材质多例) {
							材质 = mat_ptr[材质计数];
							光追材质ID = mat_ptr[材质计数]->m_材质属性ID;
							++材质计数;
						}
						else {
							材质 = mat_ptr[0];
							光追材质ID = mat_ptr[0]->m_材质属性ID;
						}



						if (材质->mf_GPU参数配置 == nullptr) {
							材质 = f_NodeCtx_get基本光照面材质();
						}



						for (auto& 材质链接网格自定义属性 : 材质->m_网格自定义属性布局) {
							S_CustomAttr a{};

							switch (材质链接网格自定义属性.m_分布方式) {
								case DEF_ShaderAttrLayout_Instance: {
									//auto& attr = *me->m_实例自定义属性区间偏移;
									auto& attr = ob->m_实例自定义属性区间偏移;

									auto& 临时转换名称 = (*材质链接网格自定义属性.m_Name);
									if (attr.find(临时转换名称) != attr.end()) {
										a.offset = attr[临时转换名称]->m_Mem.m_偏移;
										a.num = attr[临时转换名称]->m_Mem.m_数量;

										f_buf_属性索引_at(ob->m_自定义属性索引, 槽 * DEF_网格自定义属性槽数量 + 材质链接网格自定义属性.m_OffsetID) = a;
									}
									break;
								}
							}
						}



						switch (ob->m_Type) {
							case E_物体类型::t_粒子系统: {
								S_粒子系统配置* psys = f_ob_fromParticle(ob);
								for (uint32 i = 0; i < psys->m_渲染物体数量; ++i) {
									auto* me = psys->m_渲染物体网格[i];
									
									f_OE_网格自定义属性和面材质设置(me, 材质, 槽, 光追材质ID);
								}

								break;
							}
							default: {
								S_Mesh* me;
								switch (材质->m_着色线管->m_几何类型) {
									case E_几何着色类型::e_几何着色_边: {
										me = f_ob_getMesh(ob, E_物体网格元素类型::e_MT_轮廓边);
										f_me_set多维材质(me, 材质, 0, 槽);
										break;
									}
									case E_几何着色类型::e_几何着色_线: {
										//元素类型 = E_物体网格元素类型::e_MT_线;
										break;
									}
									default:
										me = f_ob_getMesh(ob, E_物体网格元素类型::e_MT_光照);
										f_me_set多维材质(me, 材质, 槽, 槽);
										break;
								}

								me = f_ob_getMesh(ob, E_物体网格元素类型::e_MT_光照);
								f_me_set多维材质(me, 材质, 槽, 槽);
								if (!me) continue;

								//uint32 面数量 = me->m_面->m_Mem.m_数量;
								//if (!面数量) continue;
								//
								//auto* 材质槽ID = me->m_材质槽ID->ptr_userData;
								//bool 槽多例 = me->m_材质槽ID->count >= 面数量;
								//
								//S_FaceElement* fe = f_buf_面元素_ptr(*me->m_面);
								//for (uint32 f = 0; f < 面数量; ++f) {
								//	if (槽多例) {
								//		if (材质槽ID[f] == 槽) fe[f].MaterialID = 光追材质ID;
								//	}
								//	else {
								//		if (材质槽ID[0] == 槽) fe[f].MaterialID = 光追材质ID;
								//	}
								//}


								f_OE_网格自定义属性和面材质设置(me, 材质, 槽, 光追材质ID);
								break;
							}
								
						}

						

						//auto& 网格自定义属性索引 = *me->m_自定义属性索引;
						//if (材质->m_网格自定义属性布局.size()) {
						//	for (auto& 材质链接网格自定义属性 : 材质->m_网格自定义属性布局) {
						//		S_CustomAttr a{};
						//
						//		switch (材质链接网格自定义属性.m_分布方式) {
						//			case DEF_ShaderAttrLayout_Point: {
						//				auto& attr = *me->m_点自定义属性区间偏移;
						//				if (attr.find(*材质链接网格自定义属性.m_Name) != attr.end()) {
						//					
						//					a.offset = attr[*材质链接网格自定义属性.m_Name].m_Mem.m_偏移;
						//					a.num = attr[*材质链接网格自定义属性.m_Name].m_Mem.m_数量;
						//
						//					f_buf_属性索引_at(网格自定义属性索引, 槽 * DEF_网格自定义属性槽数量 + 材质链接网格自定义属性.m_OffsetID) = a;
						//				}
						//				break;
						//			}
						//
						//			case DEF_ShaderAttrLayout_Face: {
						//				auto& attr = *me->m_面自定义属性区间偏移;
						//				if (attr.find(*材质链接网格自定义属性.m_Name) != attr.end()) {
						//					a.offset = attr[*材质链接网格自定义属性.m_Name].m_Mem.m_偏移;
						//					a.num = attr[*材质链接网格自定义属性.m_Name].m_Mem.m_数量;
						//
						//					f_buf_属性索引_at(网格自定义属性索引, 槽 * DEF_网格自定义属性槽数量 + 材质链接网格自定义属性.m_OffsetID) = a;
						//				}
						//				break;
						//			}
						//		}
						//	}
						//}
						//else {
						//	for (uint32 自定义属性槽ID = 0; 自定义属性槽ID < DEF_网格自定义属性槽数量; ++自定义属性槽ID) {
						//		f_buf_属性索引_at(网格自定义属性索引, 槽 * DEF_网格自定义属性槽数量 + 自定义属性槽ID) = {};
						//	}
						//}
					}
					else {
						//待以后修改其他材质的参数配置回调函数
						f_ob_set材质(ob, f_NodeCtx_get基本光照面材质(), E_物体网格元素类型::e_MT_光照);
					}
				}
			}
			break;
		}
		case 1: {
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 1, E_值类型::e_Type_材质);
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 2, E_值类型::e_Type_I8_1D);
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 3, E_值类型::e_Type_Object_1D);
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_材质);
			f_get输入插座(2)->f_set单输入();
			f_get输入插座(3)->f_set单输入();
			
			auto* socket1 = f_get输入插座(1);
			auto* socket2 = f_get输入插座(2);
			auto* socket3 = f_get输入插座(3);
			

			//socket1->f_getLinkNum();
			auto* mat = DEF_材质插座数据(socket1, 0);
			if (mat) {
				auto* 遮罩 = DEF_I8插座_1D数据(socket2);
				auto* 物体 = DEF_物体插座_1D数据(socket3);

				uint32 num = 物体->count;

				for (uint32 j = 0; j < num; ++j) {
					auto* ob = 物体->ptr_userData[j];
					uint32 实例数量 = ob->m_变换矩阵.m_Mem.m_数量;
					uint32 材质ID = mat->m_材质属性ID;
					bool 遮罩多例 = 遮罩->count >= 实例数量;

					
					if (实例数量 > ob->m_实例材质ID.size()) {
						ob->m_实例材质ID.resize(实例数量);
					}

					auto* 实例材质ID = ob->m_实例材质ID.data();
					if (f_prop_Bool(m_清除材质)) {
						for (uint32 i = 0; i < 实例数量; ++i) {
							实例材质ID[i] = 0;
						}
					}
					
					
					for (uint32 i = 0; i < 实例数量; ++i) {
						if (遮罩多例 ? 遮罩->ptr_userData[i] : 遮罩->ptr_userData[0]) {
							实例材质ID[i] = 材质ID;
						}
					}
				}
			}
			f_get输出插座(1)->f_setData(mat);
			break;
		}
		case 2: {
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 1, E_值类型::e_Type_材质1D);
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 2, E_值类型::e_Type_I8_1D);
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 3, E_值类型::e_Type_Object_1D);
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_材质1D);
			f_get输入插座(2)->f_set单输入();
			f_get输入插座(3)->f_set单输入();

			auto* socket1 = f_get输入插座(1);
			auto* socket2 = f_get输入插座(2);
			auto* socket3 = f_get输入插座(3);

			auto* mat = DEF_材质插座_1D数据(socket1, 0);
			
			auto* 遮罩 = DEF_I8插座_1D数据(socket2);
			auto* 物体 = DEF_物体插座_1D数据(socket3);

			uint32 num = 物体->count;

			for (uint32 j = 0; j < num; ++j) {
				auto* ob = 物体->ptr_userData[j];
				uint32 实例数量 = ob->m_变换矩阵.m_Mem.m_数量;
				
				bool 遮罩多例 = 遮罩->count >= 实例数量;

				if (实例数量 > ob->m_实例材质ID.size()) {
					ob->m_实例材质ID.resize(实例数量);
				}

				auto* 实例材质ID = ob->m_实例材质ID.data();
				if (f_prop_Bool(m_清除材质)) {
					for (uint32 i = 0; i < 实例数量; ++i) {
						实例材质ID[i] = 0;
					}
				}

#pragma omp parallel for num_threads(DEF_Min(16, 实例数量))
				for (int32 i = 0; i < 实例数量; ++i) {
					int8 材质 = 遮罩多例 ? 遮罩->ptr_userData[i] : 遮罩->ptr_userData[0];

					if (材质 < mat->count) {
						实例材质ID[i] = mat->ptr_userData[材质]->m_材质属性ID;
					}
				}
			}
			
			f_get输出插座(1)->f_setData(mat);
			break;
		}

		case 3: {
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 1, E_值类型::e_Type_材质1D);
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 2, E_值类型::e_Type_I8_1D);
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 3, E_值类型::e_Type_Object_1D);
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_材质1D);
			f_get输入插座(2)->f_set单输入();
			f_get输入插座(3)->f_set单输入();

			auto* socket1 = f_get输入插座(1);
			auto* socket2 = f_get输入插座(2);
			auto* socket3 = f_get输入插座(3);

			auto* mat = DEF_材质插座_1D数据(socket1, 0);

			auto* 遮罩 = DEF_I8插座_1D数据(socket2);
			auto* 物体 = DEF_物体插座_1D数据(socket3);

			int32 材质数量 = mat->count > 0 ? mat->count - 1 : 0;
			int32 开始种子 = f_prop_I32(m_随机种子);
			uint32 num = 物体->count;
			for (uint32 j = 0; j < num; ++j) {
				auto* ob = 物体->ptr_userData[j];
				uint32 实例数量 = ob->m_变换矩阵.m_Mem.m_数量;

				bool 遮罩多例 = 遮罩->count >= 实例数量;

				if (实例数量 > ob->m_实例材质ID.size()) {
					ob->m_实例材质ID.resize(实例数量);
				}

				auto* 实例材质ID = ob->m_实例材质ID.data();
				if (f_prop_Bool(m_清除材质)) {
					for (uint32 i = 0; i < 实例数量; ++i) {
						实例材质ID[i] = 0;
					}
				}

#pragma omp parallel for num_threads(DEF_Min(16, 实例数量))
				for (int32 i = 0; i < 实例数量; ++i) {
					int32 材质ID = f_random_I32({0, 材质数量 }, 开始种子 + i);

					int8 材质遮罩 = 遮罩多例 ? 遮罩->ptr_userData[i] : 遮罩->ptr_userData[0];
					if (材质遮罩) {
						实例材质ID[i] = mat->ptr_userData[材质ID]->m_材质属性ID;
					}
				}
			}
			break;
		}
		default:
			break;
	}

	


	//auto* socket3 = f_get输入插座(3);
	//uint32 物体组数量 = socket3->f_getLinkNum();
	//
	//auto* 材质组 = DEF_材质插座_1D数据(f_get输入插座(1), 0);
	//auto* mat_ptr = 材质组->ptr_userData;
	//uint32 材质数量 = 材质组->count;
	//
	//
	//for (uint32 j = 0; j < 物体组数量; ++j) {
	//	auto& 物体组 = *(S_OBArray*)(socket3->f_getData(j));
	//	uint32 物体数量 = 物体组.count;
	//
	//
	//	for (uint32 i = 0; i < 物体数量; ++i) {
	//		auto* ob = 物体组.ptr_userData[i];
	//	}
	//}

	//f_render_刷新渲染(f_NodeCtx_get默认场景());
	return false;
}

void C_设置物体材质节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);

	if (S_引擎配置::g_当前加载文件版本号 >= S_引擎配置::g_低版本号_15) {
		S_文件块 文件块 = f_file_读取文件块(f);
		if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
			const uint8* 下一次读取数据指针 = 文件块.m_data;

			if (f_file_版本对比(文件块, S_引擎配置::g_低版本号_0, S_引擎配置::g_文件版本号)) {
				下一次读取数据指针 = f_prop_Load(m_材质槽类型, 下一次读取数据指针);
				下一次读取数据指针 = f_prop_Load(m_清除材质, 下一次读取数据指针);
			}
		}
		free(文件块.m_data);
	}
	else {

	}
}

void C_设置物体材质节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	auto 文件块 = f_文件块_创建(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_引擎配置::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	f_prop_Save(m_材质槽类型, 块);
	f_prop_Save(m_清除材质, 块);

	f_file_保存文件块(f, 文件块, 块);
}

C_节点基类* f_node_创建设置物体材质节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_设置物体材质节点(ctx);
}

C_节点基类* f_node_加载设置物体材质节点(S_设备环境& ctx, FILE* f) {
	C_设置物体材质节点* node = new C_设置物体材质节点(ctx);
	return node;
}

void f_node_保存设置物体材质节点(C_节点基类* n, FILE* f) {
	C_设置物体材质节点* node = dynamic_cast<C_设置物体材质节点*>(n);
}







C_设置实例材质节点::C_设置实例材质节点(S_设备环境& ctx) : C_节点基类(DEF_设置实例材质节点, E_节点类型::e_节点Type_材质) {
	f_setWName(u"设置物体材质");
	m_Ctx = ctx;

	C_插座基类* socket;
	DEF_创建物体插座_I(u"物体", ctx);
	DEF_创建I32_1D插座_I(u"槽", ctx);
	DEF_创建物体插座_O(u"物体", ctx);


	m_材质槽类型 = f_alloc_EnumProp(nullptr, { {u"实例"}, {u"物体"} }, u"材质槽类型");
	m_材质槽类型.m_私有 = true;

}

C_设置实例材质节点::~C_设置实例材质节点() {
	f_prop_Release(m_材质槽类型);
}

bool C_设置实例材质节点::f_update() {
	auto* socket1 = f_get输入插座(1);
	auto* socket2 = f_get输入插座(2);

	auto* 物体 = DEF_物体插座数据(socket1, 0);
	auto* 材质 = DEF_UI32插座_1D数据(socket2, 0);


	switch (f_prop_enum(m_材质槽类型)) {
		case 0: {
			//f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 2, E_值类型::e_Type_I8_1D);
			//f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 3, E_值类型::e_Type_Object);
			
			uint32 num = 物体->m_变换矩阵.m_Mem.m_数量;
			//if (num > 1) {
			//	f_gbuf_resize(物体->m_实例材质ID, num);
			//}
			//else {
			//	f_gbuf_resize(物体->m_实例材质ID, 0);
			//	break;
			//}
			//
			//bool 材质多例 = 材质->count >= num;
			//
			//int32* mat_ptr = f_buf_I32_ptr(物体->m_实例材质ID);
			//for (uint32 j = 0; j < num; ++j) {
			//	mat_ptr[j] = 材质多例 ? 材质->ptr_userData[j] : 材质->ptr_userData[0];
			//}

			break;
		}
		case 1: {
			
			break;
		}
		default:
			break;
	}

	f_get输出插座(1)->f_setData(物体);
	//f_render_刷新渲染(f_NodeCtx_get默认场景());
	return false;
}

void C_设置实例材质节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	S_文件块 文件块 = f_file_读取文件块(f);
	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;

		if (f_file_版本对比(文件块, S_引擎配置::g_低版本号_0, S_引擎配置::g_文件版本号)) {
			下一次读取数据指针 = f_prop_Load(m_材质槽类型, 下一次读取数据指针);
		}
	}
	free(文件块.m_data);
}

void C_设置实例材质节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	auto 文件块 = f_文件块_创建(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_引擎配置::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	f_prop_Save(m_材质槽类型, 块);

	f_file_保存文件块(f, 文件块, 块);
}

C_节点基类* f_node_创建设置实例材质节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_设置实例材质节点(ctx);
}

C_节点基类* f_node_加载设置实例材质节点(S_设备环境& ctx, FILE* f) {
	C_设置实例材质节点* node = new C_设置实例材质节点(ctx);
	return node;
}

void f_node_保存设置实例材质节点(C_节点基类* n, FILE* f) {
	C_设置实例材质节点* node = dynamic_cast<C_设置实例材质节点*>(n);
}




C_PBR材着色器节点::C_PBR材着色器节点(S_设备环境& ctx, C_节点树* link_tree, E_着色阶段 着色阶段) : C_节点基类(DEF_PBR着色器节点, E_节点类型::e_节点Type_着色器) {
	f_setWName(u"着色器");
	m_Ctx = ctx;

	uint32 可添加删除插座起始位置 = 0;
	uint32 父节点可添加删除插座起始位置 = 0;
	m_材质线管类型 = 0;
	//m_材质 = new S_材质();
	m_着色阶段 = 着色阶段;

	switch (m_着色阶段) {
		case E_着色阶段::e_几何着色: {
			可添加删除插座起始位置 = 4;
			父节点可添加删除插座起始位置 = 0;
			break;
		}
		default: {
			可添加删除插座起始位置 = 10;
			父节点可添加删除插座起始位置 = 10;

			DEF_创建纹理插座_I(u"颜色", ctx);
			DEF_创建纹理插座_I(u"发光", ctx);
			DEF_创建纹理插座_I(u"反射", ctx);
			DEF_创建纹理插座_I(u"折射", ctx);
			DEF_创建纹理插座_I(u"粗糙", ctx);
			DEF_创建纹理插座_I(u"透明", ctx);
			DEF_创建纹理插座_I(u"法线", ctx);

			DEF_创建F32插座_I(u"透射", nullptr);
			DEF_创建F32插座_I(u"各向限异性", nullptr);
			DEF_创建F32插座_I(u"溢色", nullptr);


			DEF_纹理插座数据(f_get输入插座(1), 0)->m_格式 = E_纹理格式::e_tf_RGB32;
			DEF_纹理插座数据(f_get输入插座(2), 0)->m_格式 = E_纹理格式::e_tf_RGB32;
			DEF_纹理插座数据(f_get输入插座(3), 0)->m_格式 = E_纹理格式::e_tf_R32;
			DEF_纹理插座数据(f_get输入插座(4), 0)->m_格式 = E_纹理格式::e_tf_R32;
			DEF_纹理插座数据(f_get输入插座(5), 0)->m_格式 = E_纹理格式::e_tf_R32;
			DEF_纹理插座数据(f_get输入插座(6), 0)->m_格式 = E_纹理格式::e_tf_R32;
			DEF_纹理插座数据(f_get输入插座(7), 0)->m_格式 = E_纹理格式::e_tf_RGB32;
			DEF_纹理插座数据(f_get输入插座(3), 0)->m_默认颜色 = { 0,0,0 };


			f_构建代码_构建GPU插座变量(*f_get输入插座(1));
			f_构建代码_构建GPU插座变量(*f_get输入插座(2));
			f_构建代码_构建GPU插座变量(*f_get输入插座(3));
			f_构建代码_构建GPU插座变量(*f_get输入插座(4));
			f_构建代码_构建GPU插座变量(*f_get输入插座(5));
			f_构建代码_构建GPU插座变量(*f_get输入插座(6));
			f_构建代码_构建GPU插座变量(*f_get输入插座(7));
			f_构建代码_构建GPU插座变量(*f_get输入插座(8));

			break;
		}
	}


	C_插座基类* socket;
	DEF_创建着色器插座_O(u"着色器");


	m_节点树 = f_alloc_StrIndexProp(S_节点数据::g_着色节点树, u"着色");
	m_节点树.m_私有 = true;

	m_构建材质几何类型 = f_alloc_EnumProp(nullptr, { {u"面", u""}, {u"边", u""}, {u"线", u""} }, u"几何类型");
	m_构建材质几何类型.m_私有 = true;


	
	if (!link_tree) {
		auto* inNode = new C_输入组节点(ctx);
		auto* outNode = new C_输出组节点(ctx);

		switch (m_着色阶段) {
			case E_着色阶段::e_几何着色: {
				
				//DEF_创建F32插座_I(L"距离", nullptr);
				auto* socket1 = new C_Vec4插座(u"顶点"); inNode->f_add插座(socket1, E_插座方向::e_插座Type_输出);
				auto* socket2 = new C_Vec3插座(u"法线"); inNode->f_add插座(socket2, E_插座方向::e_插座Type_输出);
				auto* socket3 = new C_颜色插座(u"颜色"); inNode->f_add插座(socket3, E_插座方向::e_插座Type_输出);
				auto* socket4 = new C_F32插座(u"线宽"); inNode->f_add插座(socket4, E_插座方向::e_插座Type_输出);

				link_tree = f_node_Create几何着色节点树(false);

				f_几何着色器节点输出节点插座(outNode);

				f_socket_link(outNode->f_get输入插座(1), socket1);
				f_socket_link(outNode->f_get输入插座(2), socket2);
				f_socket_link(outNode->f_get输入插座(3), socket3);
				f_socket_link(outNode->f_get输入插座(4), socket4);
				break;
			}
			default: {
				
				link_tree = f_node_Create着色节点树(false, u"像素着色");

				socket = new C_Vec3插座(u"颜色"); inNode->f_add插座(socket, E_插座方向::e_插座Type_输出);
				socket = new C_Vec3插座(u"发光"); inNode->f_add插座(socket, E_插座方向::e_插座Type_输出);
				socket = new C_F32插座(u"反射"); inNode->f_add插座(socket, E_插座方向::e_插座Type_输出);
				socket = new C_F32插座(u"折射"); inNode->f_add插座(socket, E_插座方向::e_插座Type_输出);
				socket = new C_F32插座(u"粗糙"); inNode->f_add插座(socket, E_插座方向::e_插座Type_输出);
				socket = new C_F32插座(u"透明"); inNode->f_add插座(socket, E_插座方向::e_插座Type_输出);
				socket = new C_Vec3插座(u"法线"); inNode->f_add插座(socket, E_插座方向::e_插座Type_输出);
				socket = new C_F32插座(u"透射"); inNode->f_add插座(socket, E_插座方向::e_插座Type_输出);
				socket = new C_F32插座(u"各向限异性"); inNode->f_add插座(socket, E_插座方向::e_插座Type_输出);
				socket = new C_F32插座(u"溢色"); inNode->f_add插座(socket, E_插座方向::e_插座Type_输出);

				f_像素着色器节点输出节点插座(outNode);
				break;
			}
		}
		//outNode->f_add插座(new C_Vec4插座(L"颜色"), E_插座方向::e_插座Type_输入);
		inNode->m_插座可编辑 = true;
		
		link_tree->f_添加节点(inNode);
		link_tree->f_添加节点(outNode);

		//outNode->m_插座可编辑 = false;
		f_prop_Bool(link_tree->m_外部加载) = false;
		//f_prop_Str(link_tree->m_代码文件路径) += L"PBR_光线回调.spv";
	}
	f_prop_MatPtr_切换ID(m_节点树, link_tree);

	f_绑定子集节点树(link_tree);
	f_绑定this节点树(link_tree);

	std::vector<C_节点基类*> outNodes;
	f_get子集输出节点(outNodes);
	f_着色器输出节点插座GPU参数绑定(outNodes);


	
	std::vector<C_节点基类*> m_InNodes;
	f_get子集输入节点(m_InNodes);
	for (auto& e : m_InNodes) {
		e->f_set可添加删除插座起始位置(可添加删除插座起始位置, 父节点可添加删除插座起始位置);
	}
}

C_PBR材着色器节点::~C_PBR材着色器节点() {
	f_prop_Release(m_构建材质几何类型);


	std::vector<C_节点基类*> outNodes;
	f_get子集输出节点(outNodes);
	for (auto& e : outNodes) {
		uint32 num = e->f_get输入插座数量();
		for (uint32 i = 1; i < num; ++i) {
			f_构建代码_释放GPU插座变量(*e->f_get输入插座(i));
		}
	}
}

void C_PBR材着色器节点::f_get子集输入节点(std::vector<C_节点基类*>& inNodes) {
	inNodes.clear();
	for (auto& e : m_子集节点树->m_Nodes) {
		if (e->m_Type == E_节点类型::e_节点Type_组输入) {
			inNodes.emplace_back(e);
		}
	}
}

void C_PBR材着色器节点::f_get子集输出节点(std::vector<C_节点基类*>& outNodes) {
	outNodes.clear();
	for (auto& e : m_子集节点树->m_Nodes) {
		if (e->m_Type == E_节点类型::e_节点Type_组输出) {
			outNodes.emplace_back(e);
		}
	}
}

bool C_PBR材着色器节点::f_update() {
	return false;
}

std::string C_PBR材着色器节点::DEF_节点编译函数{
	std::string extern_declspec;
	
	S_着色* shader = DEF_着色器数据(f_get输出插座(1), 0);
	shader->m_ShaderIndex = m_子集节点树->m_ID;

	//std::string 属性变量;
	uint32 当前着色器节点输入插座数量 = f_get输入插座数量();
	uint32 输入节点固有参数输出插座数量 = 0;
	uint32 输入参数固有插座数量 = 0;
	uint32 自定义插座数量 = 10;



	std::vector<C_节点基类*> outNodes;
	f_get子集输出节点(outNodes);
	C_插座基类* 混合模式插座;
	//版本转换
	{
		for (auto& e : outNodes) {
			uint32 输出插座数量 = e->f_get输入插座数量();
			if (输出插座数量 < 8) {
				混合模式插座 = new C_I32插座(u"混合模式");
				e->f_add插座(混合模式插座, E_插座方向::e_插座Type_输入);

				f_构建代码_构建GPU插座变量(*混合模式插座);
			}
			else {
				混合模式插座 = e->f_get输入插座(7);
			}
		}
	}
	
	


	
	//uint32 当前
	光追属性变量 = "";
	光栅属性变量 = "";
	//#pragma omp parallel
	{
		std::vector<C_节点基类*> inNodes;
		f_get子集输入节点(inNodes);
		

		m_Code = "";
		m_ReleaseCode = "";


		//#pragma omp parallel
		for (uint32 i = 0; i < 当前着色器节点输入插座数量; ++i) {
			m_Code += f_get输入插座(i)->f_构建变量代码(0);
		}
		
		switch (m_着色阶段) {
			case E_着色阶段::e_像素着色: {
				输入节点固有参数输出插座数量 = 10;
				输入参数固有插座数量 = 10;
				自定义插座数量 = 当前着色器节点输入插座数量 - 输入节点固有参数输出插座数量;

				auto socket1 = f_get输入插座(1);
				S_纹理* tex = DEF_纹理插座数据(socket1, 0);
				if (socket1->f_get接入的数据类型() == E_值类型::e_Type_Vec3 || !(socket1->f_isLink()))
					//m_Code += "(*(vec3*)&(" + g材质_参数 + "->m_color_r)) = " + socket1->f_getCode() + ";\n";
					m_Code += g材质_参数 + "->m_color = " + socket1->f_getCode(0) + ";\n";
				else
					m_Code += g材质_参数 + "->m_colorTex = " + DEF_S(f_JIT_getGPU纹理ID)"(" + socket1->f_getCode(0) + ");\n";


				auto socket2 = f_get输入插座(2);
				tex = DEF_纹理插座数据(socket2, 0);
				if (socket2->f_get接入的数据类型() == E_值类型::e_Type_Vec3 || !(socket2->f_isLink()))
					//m_Code += "(*(vec3*)&(" + g材质_参数 + "->m_emission_r)) = " + socket2->f_getCode() + ";\n";
					m_Code += g材质_参数 + "->m_emission = " + socket2->f_getCode(0) + ";\n";
				else
					m_Code += g材质_参数 + "->m_emissionTex = " + DEF_S(f_JIT_getGPU纹理ID)"(" + socket2->f_getCode(0) + ");\n";


				auto socket3 = f_get输入插座(3);
				tex = DEF_纹理插座数据(socket3, 0);
				if (socket3->f_get接入的数据类型() == E_值类型::e_Type_Vec3 || !(socket3->f_isLink()))
					m_Code += g材质_参数 + "->m_reflect = " + socket3->f_getCode(0) + ".x;\n";
				else
					m_Code += g材质_参数 + "->m_reflectTex = " + DEF_S(f_JIT_getGPU纹理ID)"(" + socket3->f_getCode(0) + ");\n";


				auto socket4 = f_get输入插座(4);
				tex = DEF_纹理插座数据(socket4, 0);
				if (socket4->f_get接入的数据类型() == E_值类型::e_Type_Vec3 || !(socket4->f_isLink()))
					m_Code += g材质_参数 + "->m_refract = " + socket4->f_getCode(0) + ".x;\n";
				else
					m_Code += g材质_参数 + "->m_refractTex = " + DEF_S(f_JIT_getGPU纹理ID)"(" + socket4->f_getCode(0) + ");\n";


				auto socket5 = f_get输入插座(5);
				tex = DEF_纹理插座数据(socket5, 0);
				if (socket5->f_get接入的数据类型() == E_值类型::e_Type_Vec3 || !(socket5->f_isLink()))
					m_Code += g材质_参数 + "->m_roughness = " + socket5->f_getCode(0) + ".x;\n";
				else
					m_Code += g材质_参数 + "->m_roughnessTex = " + DEF_S(f_JIT_getGPU纹理ID)"(" + socket5->f_getCode(0) + ");\n";


				auto socket6 = f_get输入插座(6);
				tex = DEF_纹理插座数据(socket6, 0);
				if (socket6->f_get接入的数据类型() == E_值类型::e_Type_Vec3 || !(socket6->f_isLink()))
					m_Code += g材质_参数 + "->m_alpha = " + socket6->f_getCode(0) + ".x;\n";
				else
					m_Code += g材质_参数 + "->m_alphaTex = " + DEF_S(f_JIT_getGPU纹理ID)"(" + socket6->f_getCode(0) + ");\n";


				auto socket7 = f_get输入插座(7);
				if (socket7->f_isLink()) m_Code += g材质_参数 + "->m_normalTex = " + DEF_S(f_JIT_getGPU纹理ID)"(" + f_get输入插座(7)->f_getCode(0) + ");\n";

				auto socket8 = f_get输入插座(8);
				m_Code += g材质_参数 + "->m_transmission = " + f_get输入插座(8)->f_getCode(0) + ";\n";

				auto socket9 = f_get输入插座(9);
				m_Code += g材质_参数 + "->m_anisotropy = " + f_get输入插座(9)->f_getCode(0) + ";\n";





				m_子集节点树->m_Code = m_Code;
				m_子集节点树->m_ReleaseCode.insert(0, m_ReleaseCode);
				//std::cout << "线程2 : " << std::endl;

				//================= 着色器输入变量 ==========================
				for (auto& e : inNodes) {

					auto* outSocket1 = e->f_get输出插座(1);
					if (socket1->f_isLink()) {
						outSocket1->f_setCode("material.m_colorTex");
					}
					else {
						outSocket1->f_setCode("material.m_color");
					}

					auto* outSocket2 = e->f_get输出插座(2);
					if (socket2->f_isLink()) {
						outSocket2->f_setCode("material.m_emissionTex");
					}
					else {
						outSocket2->f_setCode("material.m_emission");
					}

					auto* outSocket3 = e->f_get输出插座(3);
					if (socket3->f_isLink()) {
						outSocket3->f_setCode("material.m_reflectTex");
					}
					else {
						outSocket3->f_setCode("material.m_reflect");
					}

					auto* outSocket4 = e->f_get输出插座(4);
					if (socket4->f_isLink()) {
						outSocket4->f_setCode("material.m_refractTex");
					}
					else {
						outSocket4->f_setCode("material.m_reflect");
					}

					auto* outSocket5 = e->f_get输出插座(5);
					if (socket5->f_isLink()) {
						outSocket5->f_setCode("material.m_roughnessTex");
					}
					else {
						outSocket5->f_setCode("material.m_roughness");
					}

					auto* outSocket6 = e->f_get输出插座(6);
					if (socket6->f_isLink()) {
						outSocket6->f_setCode("material.m_alphaTex");
					}
					else {
						outSocket6->f_setCode("material.m_alpha");
					}

					auto* outSocket7 = e->f_get输出插座(7);
					if (socket7->f_isLink()) {
						outSocket7->f_setCode("material.m_normalTex");
					}

					auto* outSocket8 = e->f_get输出插座(8);
					outSocket8->f_setCode("material.m_transmission");
				}
				
				break;
			}
			case E_着色阶段::e_几何着色: {
				输入节点固有参数输出插座数量 = 4;
				输入参数固有插座数量 = 0;
				自定义插座数量 = 当前着色器节点输入插座数量;

				for (auto& e : inNodes) {
					auto* outSocket1 = e->f_get输出插座(1);
					if(outSocket1) outSocket1->f_setCode("vert");
					
					auto* outSocket2 = e->f_get输出插座(2);
					if (outSocket2) outSocket2->f_setCode("normal");
					
					auto* outSocket3 = e->f_get输出插座(3);
					if (outSocket3) outSocket3->f_setCode("color");
					
					auto* outSocket4 = e->f_get输出插座(4);
					if (outSocket4) outSocket4->f_setCode("width");
				}
				break;
			}
		}


		//转换插座类型
		for (auto& 输入节点 : inNodes) {
			uint32 offsetID = 0;
			uint32 材质自定义属性ID = 0;

			for (uint32 i = 1; i < 自定义插座数量; ++i) {
				uint32 输入节点输出插座ID = i + 输入节点固有参数输出插座数量;
				uint32 输入插座ID = i + 输入参数固有插座数量;
				//auto* socket = f_get输入插座(i);
				auto* 着色器节点输入插座 = f_get输入插座(输入插座ID);
				auto* 输入节点输出插座 = 输入节点->f_get输出插座(输入节点输出插座ID);
				if(!输入节点输出插座) continue;

				auto* outSocket = 着色器节点输入插座->f_getLinkOutSocket(0);
				//着色器节点输入插座->f_upGPU块(0);


				if (outSocket && outSocket->m_Type == E_值类型::e_Type_网格自定义属性) {
					S_网格自定义属性& 属性 = DEF_网格自定义属性插座数据(outSocket);
					属性.m_OffsetID = offsetID;
					++offsetID;

					//f_su_切换后端插座类型(this, )
					if (输入节点输出插座->m_Type == 属性.m_Type) continue;
					
					auto 元素类型 = f_代码构建_数组元素类型(属性.m_Type);
					f_su_切换后端插座类型(输入节点, E_插座方向::e_插座Type_输出, 输入节点输出插座ID, 元素类型);
				}
				//else if (outSocket && outSocket->m_Type == E_值类型::e_Type_实例自定义属性) {
				//	S_实例自定义属性& 属性 = DEF_实例自定义属性插座数据(outSocket);
				//	
				//	auto 元素类型 = f_代码构建_数组元素类型(属性.m_Type);
				//	f_su_切换后端插座类型(输入节点, E_插座方向::e_插座Type_输出, 输入节点输出插座ID, 元素类型);
				//}
				else {
					
					auto 插座变量 = 着色器节点输入插座->f_getCode(0);

					auto offset = f_整数值转字符串(材质自定义属性ID);
					auto 插座名称 = 输入节点输出插座->f_getName() + "_" + offset;
					switch (输入节点输出插座->m_Type) {
						case E_值类型::e_Type_字体: {

							m_Code += DEF_S(f_JIT_设置材质字体纹理自定义属性偏移)"(材质," + offset + ", " + 插座变量 + ");\n";
							//输入节点输出插座->f_setCode("MaterialCA_GParam.CustomAttrPtr[" + offset + "].offset");
							//++材质自定义属性ID;
							输入节点输出插座->f_setCode(插座名称);
							光追属性变量 += "uint " + 插座名称 + " = uint(MaterialCA_GParam.CustomAttrPtr[" + offset + "].offset);\n";
							光栅属性变量 += "uint " + 插座名称 + " = uint(MaterialCA_GParam.CustomAttrPtr[" + offset + " + Element.Offset_MaterialAttr].offset);\n";
							break;
						}
						case E_值类型::e_Type_纹理: {
							if (着色器节点输入插座->f_isLink()) {
								m_Code += DEF_S(f_JIT_设置材质纹理自定义属性偏移)"(材质," + offset + ", " + 插座变量 + ");\n";
								//输入节点输出插座->f_setCode("MaterialCA_GParam.CustomAttrPtr[" + offset + "].offset");
								输入节点输出插座->f_setCode(插座名称);
								光追属性变量 += "uint " + 插座名称 + " = uint(MaterialCA_GParam.CustomAttrPtr[" + offset + "].offset);\n";
								光栅属性变量 += "uint " + 插座名称 + " = uint(MaterialCA_GParam.CustomAttrPtr[" + offset + " + Element.Offset_MaterialAttr].offset);\n";
							}
							else {
								m_Code += DEF_S(f_JIT_设置材质纹理自定义属性偏移)"(材质," + offset + ", nullptr);\n";
								//输入节点输出插座->f_setCode("MaterialCA_GParam.CustomAttrPtr[" + offset + "].offset");
								输入节点输出插座->f_setCode(插座名称);
								光追属性变量 += "uint " + 插座名称 + " = uint(MaterialCA_GParam.CustomAttrPtr[" + offset + "].offset);\n";
								光栅属性变量 += "uint " + 插座名称 + " = uint(MaterialCA_GParam.CustomAttrPtr[" + offset + " + Element.Offset_MaterialAttr].offset);\n";
							}
							//++材质自定义属性ID;
							break;
						}

						case E_值类型::e_Type_I32: {
							m_Code += DEF_S(f_JIT_添加材质着色器自定义参数)"(材质, E_值类型::e_Type_I32, " + offset + ");\n";
							m_Code += DEF_S(f_JIT_设置材质自定义属性值)"(材质, E_值类型::e_Type_I32, " + offset + ", &" + 插座变量 + ");\n";

							输入节点输出插座->f_setCode(插座名称);
							光追属性变量 += "int " + 插座名称 + " = i32_GParam.i32Ptr[ uint(MaterialCA_GParam.CustomAttrPtr[" + offset + "].offset) ];\n";
							光栅属性变量 += "int " + 插座名称 + " = i32_GParam.i32Ptr[ uint(MaterialCA_GParam.CustomAttrPtr[" + offset + " + Element.Offset_MaterialAttr].offset) ];\n";
							break;
						}
						case E_值类型::e_Type_UI32: {
							m_Code += DEF_S(f_JIT_添加材质着色器自定义参数)"(材质, E_值类型::e_Type_UI32, " + offset + ");\n";
							m_Code += DEF_S(f_JIT_设置材质自定义属性值)"(材质, E_值类型::e_Type_UI32, " + offset + ", &" + 插座变量 + ");\n";

							输入节点输出插座->f_setCode(插座名称);
							光追属性变量 += "uint " + 插座名称 + " = ui32_GParam.ui32Ptr[ uint(MaterialCA_GParam.CustomAttrPtr[" + offset + "].offset) ];\n";
							光栅属性变量 += "uint " + 插座名称 + " = ui32_GParam.ui32Ptr[ uint(MaterialCA_GParam.CustomAttrPtr[" + offset + " + Element.Offset_MaterialAttr].offset) ];\n";
							break;
						}
						case E_值类型::e_Type_F32: {
							m_Code += DEF_S(f_JIT_添加材质着色器自定义参数)"(材质, E_值类型::e_Type_F32, " + offset + ");\n";
							m_Code += DEF_S(f_JIT_设置材质自定义属性值)"(材质, E_值类型::e_Type_F32, " + offset + ", &" + 插座变量 + ");\n";

							输入节点输出插座->f_setCode(插座名称);
							光追属性变量 += "float " + 插座名称 + " = f32_GParam.f32Ptr[ uint(MaterialCA_GParam.CustomAttrPtr[" + offset + "].offset) ];\n";
							光栅属性变量 += "float " + 插座名称 + " = f32_GParam.f32Ptr[ uint(MaterialCA_GParam.CustomAttrPtr[" + offset + " + Element.Offset_MaterialAttr].offset) ];\n";
							break;
						}
						case E_值类型::e_Type_Vec2: {
							m_Code += DEF_S(f_JIT_添加材质着色器自定义参数)"(材质, E_值类型::e_Type_Vec2, " + offset + ");\n";
							m_Code += DEF_S(f_JIT_设置材质自定义属性值)"(材质, E_值类型::e_Type_Vec2, " + offset + ", &" + 插座变量 + ");\n";

							输入节点输出插座->f_setCode(插座名称);
							光追属性变量 += "vec2 " + 插座名称 + " = vec2_GParam.vec2Ptr[ uint(MaterialCA_GParam.CustomAttrPtr[" + offset + "].offset) ];\n";
							光栅属性变量 += "vec2 " + 插座名称 + " = vec2_GParam.vec2Ptr[ uint(MaterialCA_GParam.CustomAttrPtr[" + offset + " + Element.Offset_MaterialAttr].offset) ];\n";
							break;
						}
						case E_值类型::e_Type_Vec3: {
							m_Code += DEF_S(f_JIT_添加材质着色器自定义参数)"(材质, E_值类型::e_Type_Vec3, " + offset + ");\n";
							m_Code += DEF_S(f_JIT_设置材质自定义属性值)"(材质, E_值类型::e_Type_Vec3, " + offset + ", &" + 插座变量 + ");\n";

							输入节点输出插座->f_setCode(插座名称);
							光追属性变量 += "vec3 " + 插座名称 + " = vec3_GParam.vec3Ptr[ uint(MaterialCA_GParam.CustomAttrPtr[" + offset + "].offset) ];\n";
							光栅属性变量 += "vec3 " + 插座名称 + " = vec3_GParam.vec3Ptr[ uint(MaterialCA_GParam.CustomAttrPtr[" + offset + " + Element.Offset_MaterialAttr].offset) ];\n";
							break;
						}
						default:
							break;
					}
					f_构建代码_构建GPU插座变量(*输入节点输出插座);
					++材质自定义属性ID;

					if(材质自定义属性ID >= 16) break;
				}
				//m_Code += f_get输入插座(i)->f_构建变量代码(0);
			}
		}


		//#pragma omp parallel
		{
			bool 内联调用 = f_NT_是否内联调用(this);
			bool 编译 = true;
			if (内联调用) {
				if (m_子集节点树->m_以编译 & E_节点树编译位标志::e_节点编译_内联调用) {
					编译 = false;
				}
			}
			else {
				if (m_子集节点树->m_以编译 & E_节点树编译位标志::e_节点编译_外部调用) {
					编译 = false;
				}
			}

			C_材质编辑节点* mn = dynamic_cast<C_材质编辑节点*>(f_getThis节点());
			uint32 材质类型 = f_prop_UI32位域枚举(mn->m_构建材质片源类型);

			if ((编译 || m_材质线管类型 != 材质类型) && f_prop_Bool(m_子集节点树->m_外部加载) == false) {
				auto name = f_str_u16_to_u8(m_子集节点树->m_IDName);
				std::string 函数变量声明;
				std::vector<std::string> 函数定义;
				shader_code = "";
				std::string 自定义属性全局变量;

				


				
				E_几何着色类型 材质几何类型 = E_几何着色类型(f_prop_enum(m_构建材质几何类型));
				m_材质线管类型 = 材质类型;
				//int32 着色阶段类型 = f_prop_enum(m_着色阶段类型);


				m_子集节点树->m_以编译 |= E_节点树编译位标志::e_节点编译_内联调用;



				switch (m_着色阶段) {
					case E_着色阶段::e_像素着色: {
						
						if (材质类型 & 1) {
							int32 err = 0;
							auto 着色文件路径 = S_节点数据::g_工程文件着色节点代码绝对路径 + name + ".rcall";
							auto SPV = S_节点数据::g_工程文件着色节点代码绝对路径 + name + ".rspv";


							std::string 网格自定义属性;
							for (auto& e : inNodes) {
								for (uint32 i = 1; i < 自定义插座数量; ++i) {
									uint32 输入节点输出插座ID = i + 输入节点固有参数输出插座数量;
									uint32 输入插座ID = i + 输入参数固有插座数量;

									auto* 着色器节点输入插座 = f_get输入插座(输入插座ID);

									auto* outSocket = 着色器节点输入插座->f_getLinkOutSocket(0);
									if (!outSocket) continue;

									switch (着色器节点输入插座->m_Type) {
										case E_值类型::e_Type_网格自定义属性: {
											auto* socket = e->f_get输出插座(输入节点输出插座ID);
											S_网格自定义属性& 属性 = DEF_网格自定义属性插座数据(着色器节点输入插座);
											网格自定义属性 += f_网格自定义着色器数据代码生成(socket, 属性, 输入插座ID, E_着色阶段::e_光追回调);
											break;
										}
										//case E_值类型::e_Type_实例自定义属性: {
										//	auto* socket = e->f_get输出插座(输入节点输出插座ID);
										//	S_实例自定义属性& 属性 = DEF_实例自定义属性插座数据(着色器节点输入插座);
										//	网格自定义属性 += f_实例自定义着色器数据代码生成(socket, 属性, 输入插座ID, E_着色阶段::e_光追回调);
										//	break;
										//}
									}
								}
								break;
							}

							网格自定义属性 += f_代码生成_网格自定义属性全局变量节点(m_子集节点树, E_着色阶段::e_光追回调);


							//着色器代码生成
							shader_code += f_光追回调着色器引入();

							m_子集节点树->m_目标代码 = E_编译目标代码::e_编译目标代码_rCall;
							std::string 实现代码 = f_NT_编译节点树(m_子集节点树, 函数定义, 函数变量声明);
							shader_code += 函数变量声明;
							for (auto& e : 函数定义) {
								shader_code += e;
							}


							shader_code += "void main() {\n";

							shader_code += "vec3 boundOffset        = gGeom[callSceneData.InstanceIndex].boundOffset;\n";
							shader_code += "vec3 boundSize          = gGeom[callSceneData.InstanceIndex].boundSize;\n";
							shader_code += "vec3 bound_uv           = (callSceneData.Vert - boundOffset) / boundSize;\n";

							shader_code += f_光追回调着色器引用数据声明();
							
							shader_code += 网格自定义属性;
							shader_code += 光追属性变量;
							shader_code += 实现代码;
							
							shader_code += f_光追回调着色器输出参数代码构建(outNodes, m_Code);

							shader_code += "}\n";


							FILE* f = fopen(着色文件路径.c_str(), "w");
							if (f) {
								//std::vector<int32> spvCode;
								//spvCode.assign(shader_code.begin(), shader_code.end());
								f_file_保存文本(f, shader_code);
								fclose(f);
							}


							err = f_代码构建_编译着色器(着色文件路径, SPV);
							
							if (!err) {
								f_bd_安装光追材质着色器(f_NodeCtx_get默认场景()->m_光追后端, m_子集节点树->m_ID, SPV, m_子集节点树->m_ID);
								std::cout << "编译着色器" << std::endl;
							}
						}


						//S_线管创建配置 图元配置; 

						if (材质类型 & 2 && f_prop_Bool(m_子集节点树->m_外部加载) == false) {
							auto 着色文件路径 = S_节点数据::g_工程文件着色节点代码绝对路径 + name + ".frag";
							m_SPV = S_节点数据::g_工程文件着色节点代码绝对路径 + name + ".fspv";


							std::string 网格自定义属性;
							for (auto& e : inNodes) {
								for (uint32 i = 1; i < 自定义插座数量; ++i) {
									uint32 输入节点输出插座ID = i + 输入节点固有参数输出插座数量;
									uint32 输入插座ID = i + 输入参数固有插座数量;

									auto* 着色器节点输入插座 = f_get输入插座(输入插座ID);

									auto* outSocket = 着色器节点输入插座->f_getLinkOutSocket(0);
									if (!outSocket) continue;

									switch (着色器节点输入插座->m_Type) {
										case E_值类型::e_Type_网格自定义属性: {
											auto* socket = e->f_get输出插座(输入节点输出插座ID);
											S_网格自定义属性& 属性 = DEF_网格自定义属性插座数据(着色器节点输入插座);
											网格自定义属性 += f_网格自定义着色器数据代码生成(socket, 属性, 输入插座ID, E_着色阶段::e_像素着色);

											自定义属性全局变量 += f_node_getTypeName(属性.m_Type, E_节点树类型::e_type_几何着色节点树) + " " + socket->f_getCode(0) + ";\n";
											break;
										}
									}
								}
								break;
							}
							//uint32 网格属性插座数量 = m_子集节点树->m_网格属性变量->f_get输出插座数量();
							//for (uint32 i = 1; i < 网格属性插座数量; ++i) {
							//	auto* socket = m_子集节点树->m_网格属性变量->f_get输出插座(i);
							//	S_网格自定义属性& 属性 = DEF_网格自定义属性插座数据(socket);
							//	网格自定义属性 += f_网格自定义着色器数据代码生成(socket, 属性, i, E_着色阶段::e_像素着色);
							//}
							网格自定义属性 += f_代码生成_网格自定义属性全局变量节点(m_子集节点树, E_着色阶段::e_像素着色);


							//着色器代码生成
							shader_code = f_片源着色器引入();


							m_子集节点树->m_目标代码 = E_编译目标代码::e_编译目标代码_Frag;
							std::string 实现代码 = f_NT_编译节点树(m_子集节点树, 函数定义, 函数变量声明);
							shader_code += 函数变量声明;
							for (auto& e : 函数定义) {
								shader_code += e;
							}

							shader_code += 自定义属性全局变量;

							shader_code += "layout(location = 0) in vec4 vColor;\n";
							shader_code += "layout(location = 1) in vec3 vNormal;\n";
							shader_code += "layout(location = 2) in vec3 vCamera[4];\n";
							//shader_code += "layout(location = 6) in float DepthScale;\n";

							shader_code += "layout(location=0) out vec4 outColor;\n";
							shader_code += "void main() {\n";
							shader_code += "S_SceneDataCall callSceneData;\n";
							
							shader_code += f_片源着色器引用变量定义();
							shader_code += f_像素着色器网格属性定义();
							shader_code += 网格自定义属性;
							shader_code += 光栅属性变量;
							shader_code += 实现代码;
							shader_code += f_光追回调着色器输出参数代码构建(outNodes, m_Code);
							
							shader_code += "outColor = vec4(callSceneData.Color, callSceneData.alpha);\n";
							shader_code += f_偏移着色器透明链表代码构建(混合模式插座->f_getCode(0));

							//shader_code += "outColor = vec4(0,1,0,1);\n";
							shader_code += "}\n";


							FILE* f = fopen(着色文件路径.c_str(), "w");
							if (f) {
								f_file_保存文本(f, shader_code);
								fclose(f);

								int32 err = f_代码构建_编译着色器(着色文件路径, m_SPV);
								if (err) {
									m_SPV = "";
								}
							}
						}
						break;
					}
					case E_着色阶段::e_几何着色: {
						auto 着色文件路径 = S_节点数据::g_工程文件着色节点代码绝对路径 + name + ".geom";
						m_SPV = S_节点数据::g_工程文件着色节点代码绝对路径 + name + ".gspv";

						
						std::string 网格自定义属性;
						for (auto& e : inNodes) {
							for (uint32 i = 1; i < 自定义插座数量; ++i) {
								uint32 输入节点输出插座ID = i + 输入节点固有参数输出插座数量;
								uint32 输入插座ID = i + 输入参数固有插座数量;

								auto* 着色器节点输入插座 = f_get输入插座(输入插座ID);

								auto* outSocket = 着色器节点输入插座->f_getLinkOutSocket(0);
								if (!outSocket) continue;

								switch (着色器节点输入插座->m_Type) {
									case E_值类型::e_Type_网格自定义属性: {
										auto* socket = e->f_get输出插座(输入节点输出插座ID);
										S_网格自定义属性& 属性 = DEF_网格自定义属性插座数据(着色器节点输入插座);
										网格自定义属性 += f_网格自定义着色器数据代码生成(socket, 属性, 输入插座ID, E_着色阶段::e_几何着色);

										自定义属性全局变量 += f_node_getTypeName(属性.m_Type, E_节点树类型::e_type_几何着色节点树) + " " + socket->f_getCode(0) + ";\n";
										break;
									}
									default: {
										break;
									}
								}
							}
							break;
						}
						网格自定义属性 += f_代码生成_网格自定义属性全局变量节点(m_子集节点树, E_着色阶段::e_几何着色);


						//着色器代码生成
						shader_code = f_几何着色器扩展头文件();


						m_子集节点树->m_目标代码 = E_编译目标代码::e_编译目标代码_Geom;
						std::string 实现代码 = f_NT_编译节点树(m_子集节点树, 函数定义, 函数变量声明);
						shader_code += 函数变量声明;
						for (auto& e : 函数定义) {
							shader_code += e;
						}



						shader_code += f_几何着色器参数引入();
						shader_code += 自定义属性全局变量;

						switch (材质几何类型) {
							case E_几何着色类型::e_几何着色_面: {	//面
								shader_code += "void main() {\n";
								
								shader_code += f_代码构建_着色器引用数据声明();
								shader_code += "primitiveID = gl_PrimitiveIDIn + vFaceOffset[0];\n";

								shader_code += 网格自定义属性;

								shader_code += "S_FaceElement face = m_Face[vFaceAttr[0].Offset_Face + primitiveID];\n";
								shader_code += "vec3 edgeA = normalize(vVert[1] - vVert[0]);\n";
								shader_code += "vec3 edgeB = normalize(vVert[2] - vVert[0]);\n";
								shader_code += "vec3 Normal = cross(edgeA, edgeB);\n";

								shader_code += "for (int i = 0; i < 3; ++i) {\n";
									
								shader_code += "	outNormal = Normal; \n";
								shader_code += "	outPrimitiveID = primitiveID; \n";
								shader_code += "	outMeshOffset = vMeshOffset[0]; \n";

								shader_code += "	Element.MaterialID = face.MaterialID; \n";
								shader_code += "	Element.MaterialSlot = face.MaterialSlot; \n";
								shader_code += "	Element.Offset_MeshAttr = vFaceAttr[0].Offset_MeshAttr; \n";
								shader_code += "	Element.Offset_MaterialAttr = vFaceAttr[0].Offset_MaterialAttr; \n";
								
								shader_code += "	switch (i) {\n";
								shader_code += "		case 0: outBarycentrics = vec3(1, 0, 0); break; \n";
								shader_code += "		case 1: outBarycentrics = vec3(0, 1, 0); break; \n";
								shader_code += "		case 2: outBarycentrics = vec3(0, 0, 1); break; \n";
								shader_code += "	}\n";

								shader_code += 实现代码;

								shader_code += "	gVert = vVert[i]; \n";
								shader_code += "	outColor = vColor[i]; \n";
								shader_code += "	outColor.a = 1; \n";
								shader_code += "	gl_Position = gl_in[i].gl_Position; \n";
								shader_code += "	outCamera[0] = vCamera[i][0]; \n";
								shader_code += "	outCamera[1] = vCamera[i][1]; \n";
								shader_code += "	outCamera[2] = vCamera[i][2]; \n";
								shader_code += "	outCamera[3] = vCamera[i][3]; \n";

								shader_code += "	EmitVertex(); \n";
								shader_code += "}\n";

								shader_code += "EndPrimitive(); \n";

								shader_code += "}\n";
								break;
							}
							case E_几何着色类型::e_几何着色_边: {
								shader_code += f_代码构建_着色器引用数据声明();
								shader_code += f_着色器自定义全局属性();

								auto 输出参数代码 = 实现代码 + f_几何着色器输出参数代码构建(outNodes, 实现代码);
								shader_code += f_几何着色器代码生成_轮廓边(输出参数代码);
								


								shader_code += "void main() {\n";
								
								shader_code += "	primitiveID = gl_PrimitiveIDIn + vFaceOffset[0];\n";
								shader_code += "	face = m_Face[vFaceAttr[0].Offset_Face + primitiveID];\n";

								shader_code += "	Element.MaterialID = face.MaterialID;\n";
								shader_code += "	Element.MaterialSlot = face.MaterialSlot; \n ";
								shader_code += "	Element.Offset_MeshAttr = vFaceAttr[0].Offset_MeshAttr;\n ";
								shader_code += "	Element.Offset_MaterialAttr = vFaceAttr[0].Offset_MaterialAttr;\n ";
								shader_code += "	outPrimitiveID = primitiveID;\n ";

								shader_code += 网格自定义属性;

								shader_code += "	vec3 edgeA = (vVert[1] - vVert[0]);\n";
								shader_code += "	vec3 edgeB = (vVert[2] - vVert[0]);\n";
								shader_code += "	vec3 edgeC = (vVert[1] - vVert[2]);\n";
								shader_code += "	Normal = normalize(cross(edgeA, edgeB));\n";
								shader_code += "	S_Geom_MeshDrawProp AttrOffset = vFaceAttr[0];\n";
								shader_code += "	vec3 Co = (vVert[0] + vVert[1] + vVert[2]) / 3;\n";
								shader_code += "	uvec3 AdjacencyID = g_Face_AdjacencyID[AttrOffset.Offset_Face_AdjacencyID + primitiveID];\n";
								shader_code += "	uvec3 NormalAID = AdjacencyID + AttrOffset.Offset_Face_Normal;\n";
								shader_code += "	uvec3 CenterAID = AdjacencyID + AttrOffset.Offset_Face_Center;\n";
								shader_code += "	mat3 normalMat = mat3(vTranformMat[0]);\n";
								shader_code += "	vec3 viewLine = vCamera[0][1] - (vTranformMat[0] * vec4(Co, 1)).xyz;\n";
								shader_code += "	float nv = dot(normalMat * Normal, viewLine);\n";
								shader_code += "	if (nv <= 0) return;\n";
								shader_code += "	";
								shader_code += "	lineWidth[0] = 0.05;\n";
								shader_code += "	lineWidth[1] = 0.05;\n";
								shader_code += "	lineWidth[2] = 0.05;\n";
								
								shader_code += "	f_edge_width(0, lineWidth[0], vColor[0], Normal, gl_in[0].gl_Position);\n";
								shader_code += "	f_edge_width(1, lineWidth[1], vColor[1], Normal, gl_in[1].gl_Position);\n";
								shader_code += "	f_edge_width(2, lineWidth[2], vColor[2], Normal, gl_in[2].gl_Position);\n";

								shader_code += "	viewLine = vCamera[0][1] - (vTranformMat[0] * vec4(g_Face_Center[CenterAID.x], 1)).xyz;\n";
								shader_code += "	if (dot(viewLine, normalMat * g_Face_Normal[NormalAID.x]) <= 0.0) {\n";
								//shader_code += "		f_line_build(_point[0], _point[1], vColor[0], vColor[1], lineWidth[0], lineWidth[1]);\n";
								shader_code += "		f_line_build(_point[0], _point[1], _color[0], _color[1], lineWidth[0], lineWidth[1]);\n";
								shader_code += "	}\n";
								shader_code += "	viewLine = vCamera[0][1] - (vTranformMat[1] * vec4(g_Face_Center[CenterAID.y], 1)).xyz;\n";
								shader_code += "	if (dot(viewLine, normalMat * g_Face_Normal[NormalAID.y]) <= 0.0) {\n";
								//shader_code += "		f_line_build(gl_in[1].gl_Position, gl_in[2].gl_Position, vColor[1], vColor[2], lineWidth[1], lineWidth[2]);\n";
								shader_code += "		f_line_build(_point[1], _point[2], _color[1], _color[2], lineWidth[1], lineWidth[2]);\n";
								shader_code += "	}\n";
								shader_code += "	viewLine = vCamera[0][1] - (vTranformMat[2] * vec4(g_Face_Center[CenterAID.z], 1)).xyz;\n";
								shader_code += "	if (dot(viewLine, normalMat * g_Face_Normal[NormalAID.z]) <= 0.0) {\n";
								//shader_code += "		f_line_build(gl_in[2].gl_Position, gl_in[0].gl_Position, vColor[2], vColor[0], lineWidth[2], lineWidth[0]);\n";
								shader_code += "		f_line_build(_point[2], _point[0], _color[2], _color[0], lineWidth[2], lineWidth[0]);\n";
								shader_code += "	}\n";

								//shader_code += f_代码构建_着色器引用数据声明();
								//shader_code += f_几何着色器网格属性定义();
								//shader_code += 网格自定义属性;
								//shader_code += f_几何着色轮廓边生成代码构建();
								
								shader_code += "}\n";
								break;
							}
							case E_几何着色类型::e_几何着色_线: {	//线
								//shader_code += 实现代码;
								break;
							}
						}

						

						FILE* f = fopen(着色文件路径.c_str(), "w");
						if (f) {
							f_file_保存文本(f, shader_code);
							fclose(f);

							int32 err = f_代码构建_编译着色器(着色文件路径, m_SPV);
							if (err) {
								m_SPV = "";
							}
						}
						break;
					}
					default:
						break;
				}
			}
		}
		//m_Code += DEF_S(f_JIT_绑定材质着色器)"(材质, *(const S_材质*)(" + DEF_指针转字符串(m_材质) + ") );\n";
	}

	
	if (m_区域父节点) {
		m_区域父节点->m_Code += m_Code;
		//m_区域父节点->m_ReleaseCode += m_Code;
		return "";
	}

	释放 += m_ReleaseCode;
	return m_Code;
}

void C_PBR材着色器节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	S_文件块 文件块 = f_file_读取文件块(f);
	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;
	
		if (f_file_版本对比(文件块, S_引擎配置::g_低版本号_0, S_引擎配置::g_文件版本号)) {
			下一次读取数据指针 = f_prop_Load(m_构建材质几何类型, 下一次读取数据指针);
			//下一次读取数据指针 = f_文件块_读数据块(m_着色阶段, 下一次读取数据指针);
		}
	}
	free(文件块.m_data);
}

void C_PBR材着色器节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	auto 文件块 = f_文件块_创建(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_引擎配置::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	f_prop_Save(m_构建材质几何类型, 块);

	f_file_保存文件块(f, 文件块, 块);
}

void C_PBR材着色器节点::f_删除() {
	m_子集节点树->m_节点树绑定的父节点.erase(this);
	if (m_子集节点树->m_节点树绑定的父节点.size() == 0) {
		

		uint32 num = S_节点数据::g_着色节点树.size();
		for (uint32 i = 0; i < num; ++i) {
			if (S_节点数据::g_着色节点树[i].m_Ptr == m_子集节点树) {
				S_节点数据::g_着色节点树.erase(S_节点数据::g_着色节点树.begin() + i);
				f_bd_删除光追材质着色器(f_NodeCtx_get默认场景()->m_光追后端, i);
				break;
			}
		}
	}
}

void C_PBR材着色器节点::f_回收() {
	f_绑定子集节点树(m_子集节点树);
}

C_节点基类* f_node_创建设置PBR材质属性节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_PBR材着色器节点(ctx, 子节点树, E_着色阶段::e_像素着色);
}

C_节点基类* f_node_加载设置PBR材质属性节点(S_设备环境& ctx, FILE* f) {
	std::u16string 链接的节点树名称;
	E_着色阶段	m_着色阶段 = E_着色阶段::e_像素着色;

	if (S_引擎配置::g_当前加载文件版本号 >= S_引擎配置::g_低版本号_18) {
		S_文件块 文件块 = f_file_读取文件块(f);
		const uint8* 下一次读取数据指针 = 文件块.m_data;

		if (f_file_版本对比(文件块, S_引擎配置::g_低版本号_18, S_引擎配置::g_文件版本号)) {
			下一次读取数据指针 = f_解宽字符串(链接的节点树名称, 下一次读取数据指针);
			下一次读取数据指针 = f_文件块_读数据块(下一次读取数据指针, m_着色阶段);
		}
		free(文件块.m_data);
	}
	else {
		链接的节点树名称 = f_file_读取字符串(f);
	}
	

	C_节点树* tree = nullptr;
	if (S_节点数据::G用于重新映射节点树到节点的容器.find(链接的节点树名称) == S_节点数据::G用于重新映射节点树到节点的容器.end()) {
		f_node_加载节点树(ctx, f);
	}

	C_PBR材着色器节点* node = new C_PBR材着色器节点(ctx, S_节点数据::G用于重新映射节点树到节点的容器[链接的节点树名称], m_着色阶段);
	return node;
}

void f_node_保存设置PBR材质属性节点(C_节点基类* n, FILE* f) {
	C_PBR材着色器节点* node = dynamic_cast<C_PBR材着色器节点*>(n);

	auto* tree = node->f_get子集树();
	//f_file_保存字符串(f, tree->m_IDName);
	auto 文件块 = f_文件块_创建(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_引擎配置::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	f_包宽字符串(块, tree->m_IDName);
	f_文件块_写数据块(块, node->m_着色阶段);
	f_file_保存文件块(f, 文件块, 块);


	if (tree->m_未保存或加载) {
		tree->m_未保存或加载 = false;

		std::vector<C_节点树*> trees = { tree };
		f_node_保存节点树(trees, f);
	}
}





C_基于物理计算着色节点::C_基于物理计算着色节点(S_设备环境& ctx) : C_节点基类(DEF_基于物理计算着色节点, E_节点类型::e_节点Type_自定义) {
	f_setWName(u"基于物理计算");
	m_Ctx = ctx;

	C_插座基类* socket;

	DEF_创建Vec3插座_I(u"color", nullptr);
	DEF_创建Vec3插座_I(u"emission", nullptr);
	DEF_创建F32插座_I(u"reflect", nullptr);
	DEF_创建F32插座_I(u"高光", nullptr);
	DEF_创建F32插座_I(u"折射", nullptr);
	DEF_创建F32插座_I(u"粗糙", nullptr);
	DEF_创建F32插座_I(u"透明", nullptr);
	DEF_创建Vec3插座_I(u"法线", nullptr);
	//DEF_创建纹理_1D插座_I(L"颜色");

	DEF_创建Vec3插座_O(u"输出颜色");
	DEF_创建F32插座_O(u"反射", nullptr);



	m_外部加载 = f_alloc_BoolProp(nullptr, u"外部加载");
	m_外部加载.m_私有 = true;
	f_prop_Bool(m_外部加载) = false;

	//m_代码文件路径 = f_alloc_PathProp(nullptr, L"文件路径");
	//m_代码文件路径.m_私有 = true;


	f_构建代码_构建GPU插座变量(*f_get输入插座(1));
	f_构建代码_构建GPU插座变量(*f_get输入插座(2));
	f_构建代码_构建GPU插座变量(*f_get输入插座(3));
	f_构建代码_构建GPU插座变量(*f_get输入插座(4));
	f_构建代码_构建GPU插座变量(*f_get输入插座(5));
	f_构建代码_构建GPU插座变量(*f_get输入插座(6));
	f_构建代码_构建GPU插座变量(*f_get输入插座(7));
	f_构建代码_构建GPU插座变量(*f_get输入插座(8));



	//S_Material 材质 = f_material_init();
	//S_SceneDataCall DataCall{};
	//DataCall.Normal = {0,0,-1};
	//DataCall.ligthDir = {-0.5,-0.5,-0.5};
	//材质.m_specular = 3;
	//float32 brdf = cookTorranceBRDF(材质, {0.1,0,-1}, DataCall);
	//brdf;
}

C_基于物理计算着色节点::~C_基于物理计算着色节点() {
	f_prop_Release(m_外部加载);
	//f_prop_Release(m_代码文件路径);
}

bool C_基于物理计算着色节点::f_update() {
	return false;
}

std::string C_基于物理计算着色节点::DEF_节点编译函数{
	m_Code = "";
	m_ReleaseCode = "";

	if (f_prop_Bool(m_外部加载)) {

	}
	else {
		uint32 inNum = f_get输入插座数量();
		for (uint32 i = 0; i < inNum; ++i) {
			m_Code += f_get输入插座(i)->f_构建变量代码(0);
		}

		auto name = f_getName();

		auto socket1 = f_get输入插座(1);
		auto socket2 = f_get输入插座(2);
		auto socket3 = f_get输入插座(3);
		auto socket4 = f_get输入插座(4);
		auto socket5 = f_get输入插座(5);
		auto socket6 = f_get输入插座(6);
		
		if (socket1->f_isLink()) {
			//m_Code += "callMaterial.m_color = " + socket->f_getCode() + ";\n";
			//m_Code += "vec3 Color = " + socket->f_getCode() + ";\n";
		}
		//m_Code += "{ vec3 _temp_PBR_Color_ = "     + socket1->f_getCode() + ";\n";
		
		m_Code += "material.m_color = "		+ socket1->f_getCode(0) + ";\n";
		m_Code += "material.m_emission = "  + socket2->f_getCode(0) + ";\n";
		m_Code += "material.m_reflect = "	+ socket3->f_getCode(0) + ";\n";
		m_Code += "material.m_specular = "	+ socket4->f_getCode(0) + ";\n";
		m_Code += "material.m_roughness = "	+ socket6->f_getCode(0) + ";\n";
		//m_Code += "material.m_refract = "   + socket4->f_getCode() + ";\n";
		//m_Code += "material.m_roughness = " + socket5->f_getCode() + ";\n";
		//m_Code += "material.m_alpha = "     + f_get输入插座(6)->f_getCode() + ";\n";
		//m_Code += "material.m_normal = "    + f_get输入插座(7)->f_getCode() + ";\n";

		//m_Code += "vec3 LigthDir = normalize(vec3(1,1,1));\n";
		//m_Code += "vec3 " + name + " = f_MaterialPBR_calc(material, callSceneData.rayDir, callSceneData);\n";
		//m_Code += "callSceneData.ligthDir = -callSceneData.rayDir;\n";
		m_Code += "callSceneData.ligthDir = vec3(1);\n";
		m_Code += "vec3 BRDF = cookTorranceBRDF(material, -callSceneData.rayDir, callSceneData);\n";
		m_Code += "vec3 " + name + " = material.m_color * BRDF;\n";

		f_get输出插座(1)->f_setCode(name);
		

		if (socket1->m_GPU缓存.m_Buf) {
			f_buf_Vec3_at(socket1->m_GPU缓存) = DEF_Vec3插座数据(socket1);
			//((vec3*)socket1->m_GPU缓存->m_mappedPtr)[socket1->m_GPU内存偏移] = *DEF_Vec3插座数据(socket1, 0);
		}
		if (socket2->m_GPU缓存.m_Buf) {
			f_buf_Vec3_at(socket2->m_GPU缓存) = DEF_Vec3插座数据(socket2);
			//((vec3*)socket1->m_GPU缓存->m_mappedPtr)[socket2->m_GPU内存偏移] = *DEF_Vec3插座数据(socket2, 0);
		}
		if (socket3->m_GPU缓存.m_Buf) {
			f_buf_F32_at(socket3->m_GPU缓存) = DEF_F32插座数据(socket3);
			//((float32*)socket3->m_GPU缓存->m_mappedPtr)[socket3->m_GPU内存偏移] = *DEF_F32插座数据(socket3, 0);
		}
		if (socket4->m_GPU缓存.m_Buf) {
			f_buf_F32_at(socket4->m_GPU缓存) = DEF_F32插座数据(socket4);
			//((float32*)socket4->m_GPU缓存->m_mappedPtr)[socket4->m_GPU内存偏移] = *DEF_F32插座数据(socket4, 0);
		}
		if (socket5->m_GPU缓存.m_Buf) {
			f_buf_F32_at(socket5->m_GPU缓存) = DEF_F32插座数据(socket5);
			//((float32*)socket5->m_GPU缓存->m_mappedPtr)[socket5->m_GPU内存偏移] = *DEF_F32插座数据(socket5, 0);
		}
	}

	if (m_区域父节点) {
		m_区域父节点->m_Code = m_Code;
		return "";
	}
	return m_Code;
}

void C_基于物理计算着色节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	S_文件块 文件块 = f_file_读取文件块(f);
	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;

		if (f_file_版本对比(文件块, S_引擎配置::g_低版本号_0, S_引擎配置::g_文件版本号)) {
			下一次读取数据指针 = f_prop_Load(m_外部加载, 下一次读取数据指针);
		}
	}
	free(文件块.m_data);
}

void C_基于物理计算着色节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	auto 文件块 = f_文件块_创建(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_引擎配置::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	f_prop_Save(m_外部加载, 块);

	f_file_保存文件块(f, 文件块, 块);
}

C_节点基类* f_node_创建基于物理计算着色节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_基于物理计算着色节点(ctx);
}

C_节点基类* f_node_加载基于物理计算着色节点(S_设备环境& ctx, FILE* f) {
	C_基于物理计算着色节点* node = new C_基于物理计算着色节点(ctx);
	return node;
}

void f_node_保存基于物理计算着色节点(C_节点基类* n, FILE* f) {
	C_基于物理计算着色节点* node = dynamic_cast<C_基于物理计算着色节点*>(n);
}










C_几何数据节点::C_几何数据节点(S_设备环境& ctx) : C_节点基类(DEF_几何数据节点, E_节点类型::e_节点Type_自定义) {
	f_setWName(u"几何数据");
	m_Ctx = ctx;

	C_插座基类* socket;

	DEF_创建Vec3插座_O(u"顶点", nullptr);
	DEF_创建Vec3插座_O(u"法线", nullptr);
	DEF_创建Vec3插座_O(u"边界UV", nullptr);
	DEF_创建Vec3插座_O(u"大小", nullptr);
	DEF_创建Vec3插座_O(u"重心", nullptr);

	DEF_创建UI32插座_O(u"面ID", nullptr);
	//DEF_创建UI32插座_O(L"点ID", nullptr);
}

C_几何数据节点::~C_几何数据节点() {
}

bool C_几何数据节点::f_update() {
	return false;
}

std::string C_几何数据节点::DEF_节点编译函数 {
	m_Code = "";
	m_ReleaseCode = "";

	//uint32 inNum = f_get输入插座Num();
	//for (uint32 i = 0; i < inNum; ++i) {
	//	m_Code += f_get输入插座(i)->f_构建变量代码();
	//}

	auto* rt = f_getThis节点树();


	auto socket1 = f_get输出插座(1);
	auto socket2 = f_get输出插座(2);
	auto socket3 = f_get输出插座(3);
	auto socket4 = f_get输出插座(4);
	auto socket5 = f_get输出插座(5);

	auto socket6 = f_get输出插座(6);

	//switch (rt->m_目标代码) {
	//	case E_编译目标代码::e_编译目标代码_rCall: {
	//		socket1->f_setCode("callSceneData.Vert");
	//		socket2->f_setCode("callSceneData.Normal");
	//		socket3->f_setCode("bound_uv");
	//		socket4->f_setCode("boundSize");
	//		socket5->f_setCode("callSceneData.barycentrics");
	//		break;
	//	}
	//	case E_编译目标代码::e_编译目标代码_Frag: {
	//		socket1->f_setCode("callSceneData.Vert");
	//		break;
	//	}
	//	case E_编译目标代码::e_编译目标代码_Geom: {
	//		socket1->f_setCode("callSceneData.Vert");
	//		break;
	//	}
	//}

	socket1->f_setCode("callSceneData.Vert");
	socket2->f_setCode("callSceneData.Normal");
	socket3->f_setCode("bound_uv");
	socket4->f_setCode("boundSize");
	socket5->f_setCode("callSceneData.barycentrics");

	switch (rt->m_目标代码) {
		case E_编译目标代码::e_编译目标代码_rCall: {
			socket6->f_setCode("callSceneData.PrimitiveIndex");
			break;
		}
		case E_编译目标代码::e_编译目标代码_Frag: 
		case E_编译目标代码::e_编译目标代码_Geom: {
			socket6->f_setCode("inPrimitiveID");
			break;
		}
	}
	
	
	if (m_区域父节点) {
		m_区域父节点->m_Code = m_Code;
		return "";
	}
	return m_Code;
}

void C_几何数据节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	S_文件块 文件块 = f_file_读取文件块(f);
	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;

		if (f_file_版本对比(文件块, S_引擎配置::g_低版本号_0, S_引擎配置::g_文件版本号)) {
			//下一次读取数据指针 = f_prop_Load(m_外部加载, 下一次读取数据指针);
		}
	}
	free(文件块.m_data);
}

void C_几何数据节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	auto 文件块 = f_文件块_创建(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_引擎配置::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	//f_prop_Save(m_外部加载, 块);

	f_file_保存文件块(f, 文件块, 块);
}

C_节点基类* f_node_创建几何数据节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_几何数据节点(ctx);
}

C_节点基类* f_node_加载几何数据节点(S_设备环境& ctx, FILE* f) {
	C_几何数据节点* node = new C_几何数据节点(ctx);
	return node;
}

void f_node_保存几何数据节点(C_节点基类* n, FILE* f) {
	C_几何数据节点* node = dynamic_cast<C_几何数据节点*>(n);
}







C_光线数据节点::C_光线数据节点(S_设备环境& ctx) : C_节点基类(DEF_光线数据节点, E_节点类型::e_节点Type_自定义) {
	f_setWName(u"光线数据");
	m_Ctx = ctx;

	C_插座基类* socket;

	DEF_创建Vec3插座_O(u"颜色");
	DEF_创建Vec3插座_O(u"射线");
	DEF_创建Vec3插座_O(u"光线");
	DEF_创建F32插座_O(u"强度", nullptr);
	DEF_创建F32插座_O(u"距离", nullptr);
	DEF_创建Bool插座_O(u"折射面");
	DEF_创建Bool插座_O(u"面朝向");
	DEF_创建UI32插座_O(u"场景ID");
}

C_光线数据节点::~C_光线数据节点() {
}

bool C_光线数据节点::f_update() {
	return false;
}

std::string C_光线数据节点::DEF_节点编译函数{
	m_Code = "";
	m_ReleaseCode = "";
	std::string name = f_getName();
	
	auto* rt = f_getThis节点树();
	switch (rt->m_树类型) {
		case E_节点树类型::e_type_着色节点树: {
			f_get输出插座(1)->f_setCode("callSceneData.Color");
			f_get输出插座(2)->f_setCode("callSceneData.rayDir");
			f_get输出插座(3)->f_setCode("callSceneData.ligthDir");
			f_get输出插座(4)->f_setCode("callSceneData.irradiance");
			f_get输出插座(5)->f_setCode("callSceneData.irradiance");

			m_Code += "bool " + name + "_SurfaceType = bool((callSceneData.MaterialID >> 16) & " + DEF_S(DEF_SurfaceType_Refract) + ");\n";
			m_Code += "bool " + name + "_Faceforward = bool((callSceneData.MaterialID >> 16) & " + DEF_S(DEF_SurfaceType_Faceforward) + ");\n";
		
			f_get输出插座(6)->f_setCode(name + "_SurfaceType");
			f_get输出插座(7)->f_setCode(name + "_Faceforward");
			break;
		}
		default:
			break;
	}
	//f_get输出插座(1)->f_setCode(name);

	if (m_区域父节点) {
		m_区域父节点->m_Code = m_Code;
		return "";
	}
	return m_Code;
}

void C_光线数据节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	S_文件块 文件块 = f_file_读取文件块(f);
	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;

		if (f_file_版本对比(文件块, S_引擎配置::g_低版本号_0, S_引擎配置::g_文件版本号)) {
			//下一次读取数据指针 = f_prop_Load(m_外部加载, 下一次读取数据指针);
		}
	}
	free(文件块.m_data);
}

void C_光线数据节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	auto 文件块 = f_文件块_创建(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_引擎配置::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	//f_prop_Save(m_外部加载, 块);

	f_file_保存文件块(f, 文件块, 块);
}

C_节点基类* f_node_创建光线数据节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_光线数据节点(ctx);
}

C_节点基类* f_node_加载光线数据节点(S_设备环境& ctx, FILE* f) {
	C_光线数据节点* node = new C_光线数据节点(ctx);
	return node;
}

void f_node_保存光线数据节点(C_节点基类* n, FILE* f) {
	C_光线数据节点* node = dynamic_cast<C_光线数据节点*>(n);
}




C_几何UV数据节点::C_几何UV数据节点(S_设备环境& ctx) : C_节点基类(DEF_几何UV数据节点) {
	f_setWName(u"UV");
	m_Ctx = ctx;

	C_插座基类* socket;
	DEF_创建Vec3插座_I(u"采样坐标", nullptr);
	DEF_创建I32插座_I(u"层");

	DEF_创建Vec3插座_O(u"UV");

	m_UV类型 = f_alloc_EnumProp(nullptr, {
		{u"纹理坐标"},
		{u"等距圆柱"},
		{u"窗口坐标"},
	}, u"UV类型");
	m_UV类型.m_私有 = true;

	f_构建代码_构建GPU插座变量(*f_get输入插座(1));
	f_构建代码_构建GPU插座变量(*f_get输入插座(2));
	f_构建代码_分配渲染器GPU属性变量(m_UV类型);

}

C_几何UV数据节点::~C_几何UV数据节点() {
	f_构建代码_释放GPU插座变量(*f_get输入插座(1));
	f_构建代码_释放GPU插座变量(*f_get输入插座(2));
	f_构建代码_释放渲染器GPU属性变量(m_UV类型);
}

bool C_几何UV数据节点::f_update() {
	return false;
}

std::string C_几何UV数据节点::DEF_节点编译函数 {
	m_Code = "";
    m_ReleaseCode = "";
	std::string name = f_getName();


	f_buf_I32_at(m_UV类型.m_GPU缓存[0],0) = f_prop_enum(m_UV类型);

	m_Code += "vec3 " + name + " = vec3(0);\n";
	auto* socket1 = f_get输入插座(1);
	auto* socket2 = f_get输入插座(2);
	m_Code += socket1->f_构建变量代码(0);
	m_Code += socket2->f_构建变量代码(0);

	auto* rt = f_getThis节点树();
	switch (rt->m_树类型) {
	case E_节点树类型::e_type_着色节点树: {
		m_Code += "switch(" + f_代码构建_i32GPU变量(m_UV类型) + "){\n";
		m_Code += "case 0:{\n";

		switch (rt->m_目标代码) {
			case E_编译目标代码::e_编译目标代码_rCall: {
				m_Code += "if(" + socket2->f_getCode(0) + " >= gGeom[callSceneData.InstanceIndex].uvLayerAndOffset.x) break;\n";

				m_Code += "uvec3 uvIndex = uvec3(0);\n";
				m_Code += "switch(" + socket2->f_getCode(0) + "){\n";
				m_Code += "case 0: uvIndex = mesh_uvIndex.I[ callSceneData.PrimitiveIndex + gGeom[callSceneData.InstanceIndex].uvIndexOffset012.x ]; break;\n";
				m_Code += "case 1: uvIndex = mesh_uvIndex.I[ callSceneData.PrimitiveIndex + gGeom[callSceneData.InstanceIndex].uvIndexOffset012.y ]; break;\n";
				m_Code += "case 2: uvIndex = mesh_uvIndex.I[ callSceneData.PrimitiveIndex + gGeom[callSceneData.InstanceIndex].uvIndexOffset012.z ]; break;\n";
				m_Code += "case 3: uvIndex = mesh_uvIndex.I[ callSceneData.PrimitiveIndex + gGeom[callSceneData.InstanceIndex].uvIndexOffset345.x ]; break;\n";
				m_Code += "case 4: uvIndex = mesh_uvIndex.I[ callSceneData.PrimitiveIndex + gGeom[callSceneData.InstanceIndex].uvIndexOffset345.y ]; break;\n";
				m_Code += "case 5: uvIndex = mesh_uvIndex.I[ callSceneData.PrimitiveIndex + gGeom[callSceneData.InstanceIndex].uvIndexOffset345.z ]; break;\n";
				m_Code += "case 6: uvIndex = mesh_uvIndex.I[ callSceneData.PrimitiveIndex + gGeom[callSceneData.InstanceIndex].uvIndexOffset678.x ]; break;\n";
				m_Code += "case 7: uvIndex = mesh_uvIndex.I[ callSceneData.PrimitiveIndex + gGeom[callSceneData.InstanceIndex].uvIndexOffset678.y ]; break;\n";

				m_Code += "}\n";
				m_Code += "vec2 uvX = mesh_uv.UV[ uvIndex.x ];\n";
				m_Code += "vec2 uvY = mesh_uv.UV[ uvIndex.y ];\n";
				m_Code += "vec2 uvZ = mesh_uv.UV[ uvIndex.z ];\n";
				m_Code += name + ".xy = uvX * callSceneData.barycentrics.x + uvY * callSceneData.barycentrics.y + uvZ * callSceneData.barycentrics.z;\n";
				m_Code += name + ".z = 0;\n";
				break;
			}
			case E_编译目标代码::e_编译目标代码_Frag: {
				m_Code += "if(" + socket2->f_getCode(0) + " >= 4) break;\n";
				m_Code += name + ".xy = outUV[" + socket2->f_getCode(0) + "];\n";
				m_Code += name + ".z = 0;\n";
				break;
			}
		}
		
		m_Code += "break;\n";
		m_Code += "}\n";
		
		m_Code += "case 1:\n";
		m_Code += name + ".xy = " + DEF_S(f_equirectangularUV)"(" + socket1->f_getCode(0) + ");\n";
		m_Code += "break;\n";
		


		m_Code += "case 2:{\n";
			switch (rt->m_目标代码) {
				case E_编译目标代码::e_编译目标代码_Frag: {
					m_Code += name + ".xy = (gl_FragCoord.xy);\n";
					break;
				}
			}
		m_Code += "break;\n";
		m_Code += "}\n";

		m_Code += "}\n";

		//m_Code += name + ".y = (-" + name + ".y) + 1;\n";
		

		if (socket2->m_GPU缓存.m_Buf) {
			f_buf_I32_at(socket2->m_GPU缓存, 0) = DEF_I32插座数据(socket2);
		}
		break;
	}
	default:
		break;
	}

	f_get输出插座(1)->f_setCode(name);

	if (m_区域父节点) {
		m_区域父节点->m_Code = m_Code;
		return "";
	}
	return m_Code;
}

void C_几何UV数据节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	S_文件块 文件块 = f_file_读取文件块(f);
	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;

		if (f_file_版本对比(文件块, S_引擎配置::g_低版本号_0, S_引擎配置::g_文件版本号)) {
			下一次读取数据指针 = f_prop_Load(m_UV类型, 下一次读取数据指针);
		}
	}
	free(文件块.m_data);
}

void C_几何UV数据节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	auto 文件块 = f_文件块_创建(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_引擎配置::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	f_prop_Save(m_UV类型, 块);

	f_file_保存文件块(f, 文件块, 块);
}

C_节点基类* f_node_创建几何UV数据节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_几何UV数据节点(ctx);
}

C_节点基类* f_node_加载几何UV数据节点(S_设备环境& ctx, FILE* f) {
	C_几何UV数据节点* node = new C_几何UV数据节点(ctx);
	return node;
}

void f_node_保存几何UV数据节点(C_节点基类* n, FILE* f) {
	C_几何UV数据节点* node = dynamic_cast<C_几何UV数据节点*>(n);
}




C_材质网格自定义属性数据节点::C_材质网格自定义属性数据节点(S_设备环境& ctx) : C_节点基类(DEF_材质器网格自定义属性数据节点) {
	f_setWName(u"网格自定义属性");
	m_Ctx = ctx;

	C_插座基类* socket;
	DEF_创建材质插座_I(u"材质");
	DEF_网格自定义属性插座_O(u"属性");

	m_分布类型 = f_alloc_EnumProp(nullptr, {
		{u"点",		u""},
		{u"面",		u""},
		{u"实例",	u""},
		//{L"元素", ""},
							  }, u"分布类型");
	m_分布类型.m_私有 = true;

	m_属性名称 = f_alloc_LineStrProp(nullptr, u"属性类型");
	m_属性名称.m_私有 = true;

	m_属性类型 = f_alloc_EnumProp(nullptr, {
		{u"i32",	u""},
		{u"ui32",	u""},
		{u"f32",	u""},
		
		{u"vec2",	u""},
		{u"vec3",	u""},
		{u"vec4",	u""},
		{u"ivec2",	u""},
		{u"ivec3",	u""},
		{u"ivec4",	u""},
							  }, u"属性类型");
	m_属性类型.m_私有 = true;
}

C_材质网格自定义属性数据节点::~C_材质网格自定义属性数据节点() {
	f_prop_Release(m_分布类型);
	f_prop_Release(m_属性名称);
	f_prop_Release(m_属性类型);
}

bool C_材质网格自定义属性数据节点::f_update() {
	return false;
}

std::string C_材质网格自定义属性数据节点::DEF_节点编译函数 {
	m_Code = "";
	m_ReleaseCode = "";
	std::string name = f_getName();

	auto* socket1 = f_get输入插座(1);
	//auto* rt = f_getThis节点树();

	S_网格自定义属性& 属性 = DEF_网格自定义属性插座数据(f_get输出插座(1));
	f_代码构建_自定义属性设置(属性, m_属性类型, m_属性名称, m_分布类型);


	m_Code += "{\n";
	if (socket1->f_isLink()) {
		m_Code += socket1->f_构建变量代码(0);
		m_Code += DEF_S(f_JIT_添加材质自定义网格数据布局参数)"(" + socket1->f_getCode(0) + ", (S_网格自定义属性*)" + DEF_指针转字符串(&属性) + ");\n";
	}
	else {
		m_Code += DEF_S(f_JIT_添加材质自定义网格数据布局参数)"(材质, (S_网格自定义属性*)" + DEF_指针转字符串(&属性) + ");\n";
	}
	
	m_Code += "}\n";

	if (m_区域父节点) {
		m_区域父节点->m_Code = m_Code;
		return "";
	}
	return m_Code;
}

void C_材质网格自定义属性数据节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	S_文件块 文件块 = f_file_读取文件块(f);
	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;

		if (f_file_版本对比(文件块, S_引擎配置::g_低版本号_0, S_引擎配置::g_文件版本号)) {
			下一次读取数据指针 = f_prop_Load(m_分布类型, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_属性名称, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_属性类型, 下一次读取数据指针);
		}
	}
	free(文件块.m_data);
}

void C_材质网格自定义属性数据节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	auto 文件块 = f_文件块_创建(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_引擎配置::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	f_prop_Save(m_分布类型, 块);
	f_prop_Save(m_属性名称, 块);
	f_prop_Save(m_属性类型, 块);

	f_file_保存文件块(f, 文件块, 块);
}

C_节点基类* f_node_创建着色器网格自定义属性数据节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_材质网格自定义属性数据节点(ctx);
}

C_节点基类* f_node_加载着色器网格自定义属性数据节点(S_设备环境& ctx, FILE* f) {
	C_材质网格自定义属性数据节点* node = new C_材质网格自定义属性数据节点(ctx);
	return node;
}

void f_node_保存着色器网格自定义属性数据节点(C_节点基类* n, FILE* f) {
	C_材质网格自定义属性数据节点* node = dynamic_cast<C_材质网格自定义属性数据节点*>(n);
}

























//图元配置.m_参数布局 = {
//	{0, E_着色阶段::e_顶点着色, E_板载缓存类型::e_UBO},
//	{ 1, E_着色阶段::e_顶点着色, E_板载缓存类型::e_SSBO },
//	//{ 2, E_着色阶段::e_顶点着色, E_板载缓存类型::e_UBO },		//灯光方向
//	{ DEF_BINDING_WIDGET_Color, E_着色阶段::e_顶点着色, E_板载缓存类型::e_SSBO },
//
//	{ DEF_BINDING_Bones_Props, E_着色阶段::e_顶点着色, E_板载缓存类型::e_SSBO },
//	{ DEF_BINDING_Bones_Map, E_着色阶段::e_顶点着色, E_板载缓存类型::e_SSBO },
//	{ DEF_BINDING_Bones_Matrix, E_着色阶段::e_顶点着色, E_板载缓存类型::e_SSBO },
//
//	{ DEF_BINDING_LineProp, E_着色阶段::e_顶点着色, E_板载缓存类型::e_SSBO },
//
//	{ DEF_MaterialsBindID, E_着色阶段::e_像素着色, E_板载缓存类型::e_SSBO },
//	//{ DEF_TasterTexturesBindID_rgba32f, E_着色阶段::e_计算着色, E_板载缓存类型::e_SAMPLER_Array},
//	{ DEF_BINDING_Render_GlobalParam, E_着色阶段::e_像素着色, E_板载缓存类型::e_SSBO },
//	{ DEF_TasterTexturesBindID_rgba8, E_着色阶段::e_像素着色, E_板载缓存类型::e_SAMPLER_Array},
//};
//
//图元配置.m_顶点配置 = {
//	{0,sizeof(vec3),0,E_数据格式::e_F_RGB},
//	{0,sizeof(vec3),0,E_数据格式::e_F_RGB},
//	{0,sizeof(vec2),0,E_数据格式::e_F_R32G32},
//};
//
//图元配置.m_常量偏移和字节数 = { { E_着色阶段::e_顶点着色, 0, sizeof(S_Vert_MeshDrawProp) } };
//
//图元配置.m_Paths.push_back({ S_引擎配置::m_3D着色器文件根路径 + "物理光照_顶点阶段.spv", {}, E_着色阶段::e_顶点着色 });
////图元配置.m_Paths.push_back({ S_引擎配置::m_3D着色器文件根路径 + "物理光照_片源阶段.spv", {}, E_着色阶段::e_像素着色 });
//图元配置.m_Paths.push_back({ m_SPV, {}, E_着色阶段::e_像素着色 });
//
//
//S_线管创建参数 线管参数({ 1024, 1024 });
//线管参数.m_绘制方式 = E_绘制方式::e_三角形;
//线管参数.m_填充模式 = E_填充模式::e_填充面;
//线管参数.m_采样 = m_Ctx.m_采样数;
//
//f_df_销毁材质着色器(m_材质);
//f_df_创建材质着色器(m_Ctx, m_材质, 图元配置, 线管参数);
//
//m_材质->mf_GPU参数配置 = (fp_set材质GPU参数配置)f_update着色器参数配置;









//C_着色器节点::C_着色器节点(S_设备环境& ctx, C_节点树* link_tree) : C_节点基类(DEF_着色器节点, E_节点类型::e_节点Type_材质) {
//	f_setWName(L"着色器");
//	m_Ctx = ctx;
//
//	C_插座基类* socket;
//	DEF_创建着色器插座_O(L"着色器");
//
//
//	m_外部加载 = f_alloc_BoolProp(nullptr, L"外部加载");
//	m_外部加载.m_私有 = true;
//	f_prop_Bool(m_外部加载) = false;
//
//	m_着色阶段 = f_alloc_EnumProp(nullptr, { {L"光追回调", ""}, {L"顶点", ""}, {L"几何", ""}, {L"片源", ""}, {L"计算", ""}}, L"函数名称");
//	m_着色阶段.m_私有 = true;
//	
//	m_节点树 = f_alloc_StrIndexProp(S_节点数据::g_着色节点树, L"");
//	m_节点树.m_私有 = true;
//
//	m_源码类型 = f_alloc_EnumProp(nullptr, { {L"spv", ""}, {L"glsl", ""} }, L"着色文件类型");
//	m_源码类型.m_私有 = true;
//
//
//	if (!link_tree) {
//		link_tree = f_node_Create着色节点树(false, L"着色");
//
//		auto* inNode = new C_输入组节点(ctx);
//		auto* outNode = new C_输出组节点(ctx);
//
//		f_su_拷贝插座(this, inNode, E_插座方向::e_插座Type_输入, E_插座方向::e_插座Type_输出);
//		//f_su_拷贝插座(this, outNode, E_插座方向::e_插座Type_输出, E_插座方向::e_插座Type_输入);
//		f_像素着色器节点输出节点插座(outNode);
//
//
//		inNode->m_插座可编辑 = true;
//		//link_tree->f_添加节点(inNode);
//		//link_tree->f_添加节点(outNode);
//		f_node_节点树添加节点(link_tree, inNode);
//		f_node_节点树添加节点(link_tree, outNode);
//	}
//	f_prop_MatPtr_切换ID(m_节点树, link_tree);
//
//	C_节点基类::f_绑定子集节点树(link_tree);
//	f_绑定this节点树(m_当前节点所在节点树);
//
//
//	std::vector<C_节点基类*> outNodes;
//	f_get子集输出节点(outNodes);
//	f_着色器输出节点插座GPU参数绑定(outNodes);
//}
//
//C_着色器节点::~C_着色器节点() {
//}
//
//void C_着色器节点::f_get子集输入节点(std::vector<C_节点基类*>& inNodes) {
//	inNodes.clear();
//	for (auto& e : m_子集节点树->m_Nodes) {
//		if (e->m_Type == E_节点类型::e_节点Type_组输入) {
//			inNodes.emplace_back(e);
//		}
//	}
//}
//
//void C_着色器节点::f_get子集输出节点(std::vector<C_节点基类*>& outNodes) {
//	outNodes.clear();
//	for (auto& e : m_子集节点树->m_Nodes) {
//		if (e->m_Type == E_节点类型::e_节点Type_组输出) {
//			outNodes.emplace_back(e);
//		}
//	}
//}
//
//bool C_着色器节点::f_update() {
//	S_着色* shader = DEF_着色器数据(f_get输出插座(1), 0);
//	shader->m_ShaderIndex = m_子集节点树->m_ID;
//
//	return false;
//}
//
//std::string C_着色器节点::DEF_节点编译函数{
//	std::string extern_declspec;
//	
//	//#pragma omp parallel
//	{
//		//#pragma omp parallel
//		{
//			m_Code = "";
//			m_ReleaseCode = "";
//
//			uint32 inNum = f_get输入插座数量();
//			for (uint32 i = 0; i < inNum; ++i) {
//				m_Code += f_get输入插座(i)->f_构建变量代码(0);
//			}
//
//
//			m_子集节点树->m_Code = m_Code;
//			m_子集节点树->m_ReleaseCode = m_ReleaseCode;
//			std::cout << "线程2 : " << std::endl;
//		}
//
//
//		//#pragma omp parallel
//		{
//			if (m_子集节点树->m_以编译) {
//
//			}
//			else {
//				m_子集节点树->m_以编译 = 1;
//				int32 err = -1;
//
//				if (f_prop_Bool(m_子集节点树->m_外部加载) == false) {
//				//着色器代码生成
//					std::string shader_code;
//					shader_code += "#version 460 core\n";
//					shader_code += "#extension GL_EXT_ray_tracing : require\n";
//					shader_code += "#extension GL_EXT_scalar_block_layout : enable\n";
//					shader_code += "#extension GL_EXT_buffer_reference2 : require\n";
//					shader_code += "#extension GL_EXT_shader_explicit_arithmetic_types_int64 : require\n";
//					shader_code += "#extension GL_GOOGLE_include_directive : enable\n";
//
//
//					shader_code += "#include \"./shader_std.h\"\n";
//					shader_code += "#include \"./shader_rcall.h\"\n";
//					shader_code += "#include \"./shader_built_in_functions.h\"\n";
//					shader_code += "#include \"./shader_PBR.h\"\n";
//					shader_code += "#include \"./shader_rcall.h\"\n";
//					shader_code += "#include \"./shader_ob.h\"\n";
//					shader_code += "#include \"./shader_texture.h\"\n";
//
//
//					std::vector<std::string> 函数定义;
//					std::string 函数变量声明;
//					std::string 实现代码 = f_NT_编译节点树(m_子集节点树, 函数定义, 函数变量声明);
//
//
//					shader_code += 函数变量声明;
//					for (auto& e : 函数定义) {
//						shader_code += e;
//					}
//
//					shader_code += "void main() {\n";
//					shader_code += f_光追回调着色器引用数据声明();
//					shader_code += 实现代码;
//
//					std::vector<C_节点基类*> outNodes;
//					f_get子集输出节点(outNodes);
//					shader_code += f_光追回调着色器输出参数代码构建(outNodes, m_Code);
//
//					shader_code += "}\n";
//
//
//					//auto path = S_节点数据::g_工程文件着色节点代码路径;
//					auto path = f_WStringToString(f_prop_Str(m_子集节点树->m_代码文件路径));
//					auto name = f_file_取无后缀文件名(path);
//					if (name == ".") {
//						//name = f_WStringToString(f_prop_Str(m_子集节点树->m_函数名称));
//						//f_prop_Str(m_子集节点树->m_代码文件路径) += f_prop_Str(m_子集节点树->m_函数名称) + L".spv";
//						name = f_WStringToString(m_子集节点树->m_IDName);
//						f_prop_Str(m_子集节点树->m_代码文件路径) += m_子集节点树->m_IDName + L".spv";
//					}
//					auto 着色文件路径 = f_WStringToString(S_引擎配置::g_工程文件临时路径) + name + ".rcall";
//					FILE* f = fopen(着色文件路径.c_str(), "w");
//					if (f) {
//						f_file_保存文本(f, shader_code);
//						fclose(f);
//					}
//
//
//					std::string cmd = f_WStringToString(S_引擎配置::m_着色器编译器路径);
//					cmd += " -V " + 着色文件路径;
//					cmd += " -o " + path;
//					cmd += " -I" + f_WStringToString(S_引擎配置::m_着色器头文件路径);
//					cmd += " --target-env vulkan1.3";
//
//					err = system(cmd.c_str());
//					//f_bd_GLSLtoSPV(E_着色阶段::e_光追回调, shader_code, "d:/call_shader.spv");
//					std::cout << "线程1 : " << err << std::endl;
//				}
//
//
//				if (!err) {
//					std::string path = f_WStringToString(f_prop_Str(m_子集节点树->m_代码文件路径));
//					f_bd_安装光追材质着色器(f_NodeCtx_get默认场景()->m_光追后端, m_子集节点树->m_ID, path, m_子集节点树->m_ID);
//					std::cout << "编译着色器" << std::endl;
//				}
//
//			}
//
//
//		}
//
//	}
//
//	S_着色* shader = DEF_着色器数据(f_get输出插座(1), 0);
//	shader->m_ShaderIndex = m_子集节点树->m_ID;
//
//
//
//	if (m_区域父节点) {
//		m_区域父节点->m_Code += m_Code;
//		return "";
//	}
//
//	释放 += m_ReleaseCode;
//	return m_Code;
//
//}
//
//void C_着色器节点::f_读取(FILE* f) {
//	C_节点基类::f_读取(f);
//}
//
//void C_着色器节点::f_写入(FILE* f) {
//	C_节点基类::f_写入(f);
//}
//
//C_节点基类* f_node_创建着色器节点(S_设备环境& ctx, C_节点树* 子节点树) {
//	return new C_着色器节点(ctx, 子节点树);
//}
//
//C_节点基类* f_node_加载着色器节点(S_设备环境& ctx, FILE* f) {
//	std::wstring 链接的节点树名称 = f_file_读取字符串(f);
//
//	if (S_节点数据::G用于重新映射节点树到节点的容器.find(链接的节点树名称) == S_节点数据::G用于重新映射节点树到节点的容器.end()) {
//		f_node_加载节点树(ctx, f);
//	}
//
//	C_着色器节点* node = new C_着色器节点(ctx, S_节点数据::G用于重新映射节点树到节点的容器[链接的节点树名称]);
//	return node;
//}
//
//void f_node_保存着色器节点(C_节点基类* n, FILE* f) {
//	C_着色器节点* node = dynamic_cast<C_着色器节点*>(n);
//
//	auto* tree = node->f_get子集树();
//	f_file_保存字符串(f, tree->m_IDName);
//
//	if (tree->m_未保存或加载) {
//		tree->m_未保存或加载 = false;
//
//		std::vector<C_节点树*> trees = { tree };
//		f_node_保存节点树(trees, f);
//	}
//}





//switch (属性.m_Type) {
					//	case E_值类型::e_Type_I32_1D: {
					//		f_su_切换后端插座类型(输入节点, E_插座方向::e_插座Type_输出, 输入节点输出插座ID, E_值类型::e_Type_I32);
					//		break;
					//	}
					//	case E_值类型::e_Type_UI32_1D: {
					//		f_su_切换后端插座类型(输入节点, E_插座方向::e_插座Type_输出, 输入节点输出插座ID, E_值类型::e_Type_UI32);
					//		break;
					//	}
					//	case E_值类型::e_Type_F32_1D: {
					//		f_su_切换后端插座类型(输入节点, E_插座方向::e_插座Type_输出, 输入节点输出插座ID, E_值类型::e_Type_F32);
					//		break;
					//	}
					//	case E_值类型::e_Type_Vec2_1D: {
					//		f_su_切换后端插座类型(输入节点, E_插座方向::e_插座Type_输出, 输入节点输出插座ID, E_值类型::e_Type_Vec2);
					//		break;
					//	}
					//	case E_值类型::e_Type_Vec3_1D: {
					//		f_su_切换后端插座类型(输入节点, E_插座方向::e_插座Type_输出, 输入节点输出插座ID, E_值类型::e_Type_Vec3);
					//		break;
					//	}
					//	case E_值类型::e_Type_Vec4_1D: {
					//		f_su_切换后端插座类型(输入节点, E_插座方向::e_插座Type_输出, 输入节点输出插座ID, E_值类型::e_Type_Vec4);
					//		break;
					//	}
					//	case E_值类型::e_Type_iVec2_1D: {
					//		f_su_切换后端插座类型(输入节点, E_插座方向::e_插座Type_输出, 输入节点输出插座ID, E_值类型::e_Type_iVec2);
					//		break;
					//	}
					//	case E_值类型::e_Type_iVec3_1D: {
					//		f_su_切换后端插座类型(输入节点, E_插座方向::e_插座Type_输出, 输入节点输出插座ID, E_值类型::e_Type_iVec3);
					//		break;
					//	}
					//	case E_值类型::e_Type_iVec4_1D: {
					//		f_su_切换后端插座类型(输入节点, E_插座方向::e_插座Type_输出, 输入节点输出插座ID, E_值类型::e_Type_iVec4);
					//		break;
					//	}
					//	default:
					//		break;
					//}

